home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / docs / opentech.asc < prev    next >
Encoding:
Text File  |  1993-11-22  |  103.5 KB  |  1,491 lines

  1. 1993 Apple Computer, Inc.        
  2.  
  3. OpenDoc Technical Summary
  4. By
  5. The OpenDoc Design Team
  6.  
  7.  
  8. Version 1.0
  9. October 18, 1993
  10.  
  11.   1993 Apple Computer, Inc. All Rights Reserved.
  12. Apple, the Apple logo, Macintosh, Mac, and OpenDoc are registered trademarks of Apple Computer, Inc.
  13.  
  14. AppleScript, QuickDraw, QuickDraw GX and QuickTime are trademarks of Apple Computer, Inc.
  15. MacDraw and MacWrite are registered trademarks of Claris Corporation.
  16. CORBA is a trademark of the Object  Management Group, Inc. (OMG). OMG, the OMG logo, and 'Object Management' are registered trademarks of OMG.
  17. OS/2 and System Object Model are registered trademarks of International Business Machines Corporation.
  18. Microsoft is a registered trademark of Microsoft Corporation.
  19. Motif is a trademark of Open Software Foundation, Inc.
  20. OPEN LOOK  is a registered trademark of UNIX Software Laboratories, Inc.
  21.  
  22. Table Of Contents    
  23. Summary    1
  24. Introduction    3
  25. Goals    3
  26. Compound document support    3
  27. Scriptability    3
  28. Collaboration Support    3
  29. Cross-platform    3
  30. Replaceability    4
  31. Parsimony    4
  32. Chapter 1. Basic Concepts    5
  33. Compound documents    5
  34. Change to content centered model    5
  35. Enabling compound documents    5
  36. Parts    5
  37. Part handlers    8
  38. Editors and viewers    8
  39. Events    8
  40. Registration    9
  41. Storage    9
  42. Run-time    9
  43. Layout    10
  44. Customization    10
  45. Scripting    10
  46. Content centered scripting    10
  47. Compound document scripting    10
  48. Compound UI    10
  49. Collaboration    10
  50. Mail    11
  51. Collaboration between parts    11
  52. Shared documents    11
  53. Document interchange    11
  54. Cross-platform    12
  55. Chapter 2. Class Library    13
  56. Design goals    13
  57. Cross-platform    13
  58. Easy Retrofit    13
  59. Replaceable    14
  60. Extensible    14
  61. Not a framework    14
  62. Sub-systems    14
  63. Shell    14
  64. Storage    15
  65. Imaging    18
  66. HI Events    19
  67. Semantic Events    19
  68. Class Hierarchy    20
  69. Abstract Base Classes    20
  70. RefCounted Objects    20
  71. Extensible Objects    20
  72. Persistent Objects    20
  73. Implementation Classes    21
  74. Storage    21
  75. Imaging    21
  76. HI Events    21
  77. Semantic Events    21
  78. Service Classes    21
  79. Chapter 3. Programmer Model    25
  80. Programming environment    25
  81. Part Editor (new from scratch)    27
  82. Produce content model    27
  83. Implement core data engine    27
  84. Implement storage code    27
  85. Basic storage of the part    27
  86. Data transfer    27
  87. Linking    28
  88. Collaboration and drafts    28
  89. Implement rendering code    28
  90. Implement event handling code    28
  91. Implement scripting code    29
  92. Implement desired extension interfaces    29
  93. Package the part handler    30
  94. Create stationery    30
  95. Additional steps if writing a containing part handler    30
  96. Add embedded parts to content model    30
  97. Add frame management to event handling code    30
  98. Add frame management to rendering code    30
  99. Add embedding support to storage code    30
  100. Part Editor (refit existing application)    30
  101. Determine content model    30
  102. Factor core data engine    30
  103. Refit storage code    31
  104. Refit rendering code    31
  105. Refit event handling code    31
  106. Refit scripting code    31
  107. Container    31
  108. Add some initialization code    32
  109. Refit storage code    32
  110. Refit event handling code    32
  111. Add embedded parts to content model    32
  112. Add frame management to event handling code    32
  113. Add frame management to rendering code    32
  114. Add embedding support to storage code    33
  115. Platform Vendor    33
  116. Implement a storage system    33
  117. Implement an arbitrator    33
  118. Implement event delivery    33
  119. Implement a window & layout system    33
  120. Implement a runtime environment    34
  121. Chapter 4. OpenDoc API    35
  122. Notes about Style    35
  123. Language Choice    35
  124. Distributed operation    35
  125. PlfmType.h    35
  126. XMPTypes.h, XMPTypes.r    35
  127. Exception handling    35
  128. Class information    35
  129. Class categories    36
  130. Developer implementations    36
  131. Part    36
  132. Dispatch Module    36
  133. Platform facilities    36
  134. Canvas    36
  135. Shape    37
  136. Transformation    37
  137. Platform implementations    37
  138. Iterators    37
  139. Arbitrator    37
  140. Dispatcher    37
  141. Storage    37
  142. Container    38
  143. Document    38
  144. Draft    38
  145. Storage Unit    38
  146. Clipboard    38
  147. Storage Unit    38
  148. Drag & Drop    38
  149. Storage Unit    39
  150. Link    39
  151. Storage Unit    39
  152. Semantic Interface    39
  153. Message Interface    39
  154. Common implementations    39
  155. Name Resolver    39
  156. Name Space    39
  157. Window State    39
  158. Window    40
  159. Frame    40
  160. Future areas for expansion    40
  161. Authorization    40
  162. Store & forward messaging    40
  163. Digital signature & encryption    40
  164. Compound Human Interface    40
  165. Detailed APIs    40
  166. Appendix A. Public API Subset    41
  167. Basic part development    41
  168. XMPPart    41
  169. XMPExtension    43
  170. Basic part environment    43
  171. XMPArbitrator    43
  172. XMPCanvas    43
  173. XMPClipboard    43
  174. XMPDispatcher    43
  175. XMPDraft    44
  176. XMPDragAndDrop    44
  177. XMPFocusSet    45
  178. XMPFrame    45
  179. XMPLayout    46
  180. XMPLink    46
  181. XMPMenuBar    46
  182. XMPNameSpace    47
  183. XMPShape    47
  184. XMPStorageSystem    47
  185. XMPStorageUnit    48
  186. XMPStorageUnitCursor    48
  187. XMPStorageUnitView    48
  188. XMPSymbols    49
  189. XMPSession    49
  190. XMPTransform    50
  191. XMPTranslation    50
  192. XMPTypeSet    50
  193. XMPUndo    50
  194. XMPWindow    51
  195. XMPWindowState    51
  196. Scripting & semantic event processing    51
  197. XMPSemanticInterface    51
  198. XMPMessageInterface    53
  199. XMPNameResolver    53
  200. Extended event dispatch control    53
  201. XMPArbitrator    53
  202. XMPFocusModule    54
  203. XMPDispatcher    54
  204. XMPDispatchModule    54
  205. Extended draft control    54
  206. XMPDocument    54
  207. Container application implementors    55
  208. XMPContainer    55
  209. XMPDocument    55
  210.  
  211. Summary
  212. OpenDoc is the enabling technology which will bring a new class of applications and documents to the Macintosh, Windows, UNIX, OS/2, and other platforms. With OpenDoc, Apple, other platform vendors, and hardware and software developers will be in a better position to deliver new hardware and software technologies to users, to deliver better client/client/server integration to corporate users, and to deliver multimedia content to users with unprecedented ease.
  213. OpenDoc itself enables a class of applications which can support compound documents, which can be customized, used collaboratively, and are available cross-platform. In doing so, it will fundamentally change the nature of software development for personal computers.
  214. This document describes the requirements for the base OpenDoc technology: a set of libraries which developers can use to build compound document editors and viewers.  The APIs for this base technology are extensive, covering hundreds of pages of material.
  215. This document may or may not be delivered with attached APIs. These APIs will be generally available at a later date.
  216.  
  217. Introduction
  218. OpenDoc is an architecture for applications. Architecture is a word with many connotations, so we need to be a little more clear about our specific meaning of the term. Let's look at a definition for architecture from Webster's Dictionary:
  219. Architecture (n.)  A method or style of building. A unifying form or structure.
  220. To apply this same idea to software, we might end up with a definition as follows:
  221. Application architecture (n.) A style of building applications, characterized by a particular program structure and user interface.
  222. The purpose of an application architecture is to create a style of building applications. A recipe, if you will, for putting together a fine program.
  223. This document describes how to create an application which will meet the needs of users, developers, and platform vendors into the coming decade. OpenDoc applications provide greatly improved content integration, collaboration, customizability, and cross-
  224. platform interoperability.
  225.  
  226. Goals
  227. OpenDoc has several major goals, each of which is equally important to the success of the package. 
  228.  
  229. Compound document support
  230. The major noticeable feature of OpenDoc is a set of interoperability protocols designed to allow code produced by independent development teams to cooperate to produce a single document for the end user. We provide APIs designed to allow these cooperating
  231. executables to negotiate about human interface resources, document layout on screen and on printing devices, share storage containers, and create data links to one another.
  232.  
  233. Scriptability
  234. A second major feature is the ability to have parts be scriptable, and thus enabling end users to customize their applications to user-specific tasks. In a compound document environment, this capability allows sophisticated users to create simple applicat
  235. ions using standard document editing procedures. It also allows programmers to disguise complex client applications as documents.
  236.  
  237. Collaboration Support
  238. OpenDoc documents must have the ability to be passed through review cycles with minimal pain on the part of users.  OpenDoc 1.0 implements a draft capability, which protects OpenDoc documents from data loss in cross-platform situations.
  239.  
  240. Cross-platform
  241. OpenDoc was designed as a cross-platform architecture. To this end, we will be releasing OpenDoc as a reference specification and implementation. Commitments exist for implementations on AIX, OS/2, Windows, and Macintosh computers, with support for more platforms available soon.
  242.  
  243. Replaceability
  244. To reach our goal of cross-platform adoption, OpenDoc must allow replacement of the implementation of any subsystem on any platform. Toward this end, we intend to fully document all meta-data for persistent storage so that interoperability is maintained.
  245.  
  246. Parsimony
  247. The cross-platform arena is fraught with pitfalls. We have avoided attempting to specify drawing systems, coordinate systems, window systems, human interface guidelines, and many other platform specific elements. By doing so, we hope to make the architecture more generally available.
  248.  
  249. Chapter 1. Basic Concepts
  250. OpenDoc is an architecture designed to enable the construction of compound, collaborative, customizable, and cross-platform applications. This segment of the document is designed to introduce you to the basic concepts of OpenDoc, to prepare you for the more detailed chapters to come later.
  251. You should know that certain features have been designed as a part of OpenDoc which are not covered in this document. These include: authentication, digital signatures, store & forward messaging, compound user interface, and simultaneous access to documents. They are not covere here because they are not a part of the initial release.
  252.  
  253. Compound documents
  254. OpenDoc enables the creation of compound documents. By this, we mean documents which are created and edited by several cooperating applications working within a single document. 
  255.  
  256. Change to content centered model
  257. OpenDoc fundamentally changes the meaning of the term document. In the present desktop computing realm, a document has a type which is used to choose the application which will help the user edit, view, and print the document. In OpenDoc, a document is a collection of parts, each of which is much like a present day document. Each part has a type, and this type is used to choose a part handler which will help the user edit, view, and print that part of the document. 
  258. The result of this shift in perspective is a significant change in how application software is written. The document is no longer a monolithic block of content, but is instead composed of many smaller blocks of content which together make up the content of the document. Since no single application has complete control of the document, protocols must be created to keep the various cooperating pieces of code from getting in one another's way. This is a pervasive change in how applications work. Protocols covering storage management, event distribution, run-time model, and human interface management must be followed if the document is to remain editable and uncorrupted.
  259. This is a lot of work, but the rewards are great. Once OpenDoc is implemented, a whole class of existing user problems will go away. Users will be able to put any kind of content into any document without worrying whether the application can handle that kind of data. 
  260.  
  261. Enabling compound documents
  262. The central fact of life in a compound document world is that no single developer team is in control of a given document. The compound document integrates many different kinds of information, run by many different pieces of executable code, from many different developers.
  263.  
  264. Parts
  265. Parts are the boundaries in the document where one kind of content ends and another begins. Any document may have many different kinds of parts. These parts are a central notion in OpenDoc, since they give the user a way to predict what will happen, and how, when a change is made to a compound document.
  266. A part can embed another part, and know little or nothing about the information contained in that embedded part. The human interface team has constructed an interface designed to make it simple and convenient to select and operate on these embedded parts.
  267. Every document has a single part at its top level, the root part, into which all other parts are embedded. Of course, some parts are embedded in parts which are themselves embedded in the root part. Transitively, though, every part is embedded in the root part of the document.
  268. Here's an example document which we can use to illustrate the concept of parts. 
  269.  
  270. In this example document, the root part is an object-style graphic editor. In the upper left corner, there are two content objects, a rectangle and an ellipse. A clock part has been embedded in the top right corner. Towards the center and bottom left, a chart part overlaps a table part. In the right center, a text part is embedded. A button part is embedded in the text part. A second button part is embedded in the graphics part, at the bottom center of the document. In the illustration below, a thick gray border is drawn around each part.
  271.  
  272. The key element of the notion of parts is that each part of a document has its own content model. By a content model, we mean the model of objects and operations that is presented to an end user of the part. The content model changes at the boundary between parts. Let's look at an example.
  273. In the canonical document shown above, there is a text part. Inside the text part, the user sees lines, words, paragraphs, characters, and an embedded button part. Internally, the program in charge of the part might have a model which includes run-length encoding arrays for style information, line end arrays, and similar arcana. These are not presented to the user, though, so they are not part of the content model. In another part, the graphics part at the root of the document, the content objects may look very different. Circles, rectangles, and lines are content objects we would expect to see in a graphic part.
  274. The content model also includes operations like selection, deletion, insertion, setting properties, and so on. Again, there are probably low-level internal routines, like piece table routines that allow efficient insertion of text. Just as with the objects, the ones considered part of the content model are the ones a user can access.
  275. So we can properly define parts as bounded sets of content which have a single content model. Whenever the content model changes, a part boundary has been reached. 
  276. Notice that the rectangle and ellipse in the upper left corner of the example document are not parts at all, but are instead referred to as content objects. This brings up a key point. An embedded part is fundamentally distinct from the ordinary content elements like simple shapes, characters, cells, etc.. When a part boundary is reached, extra protocols must be invoked because more than one part handler is involved in giving the user access to the information.
  277. Thus, in a working OpenDoc document, a part is both a user visible abstraction and a useful programmatic abstraction. A given part can be edited with minimal impact on the surrounding content of the document. Its storage can be managed independently of other parts. 
  278.  
  279. Part handlers
  280. Part handlers are the 'applications' in the OpenDoc architecture. When a part is being displayed or edited, a part handler is invoked to perform those tasks. Just as an application performs basic editing, display, and printing tasks for a given document, 
  281. part handlers perform these functions for a part. In terms of the content model we just talked about, the part handler provides the content model of the part.
  282. A part handler is responsible for the following basic things:
  283.   Displaying the part (both on-screen and printing). The part handler may be asked to display the part on a dynamic medium such as a screen or a static medium such as the printed page.
  284.   Editing the part. The part handler must accept events and change the state of the part so that the user can edit and script the part.
  285.   Storage management (persistent and runtime) for the part. The part handler must be able to read the part from persistent storage into main memory, manage the run-time storage associated with the part, and write the part back out to persistent storage.
  286. A part and its handler together form the equivalent of a programmatic object, in the object-oriented programming sense of the word. The part provides the state information, while the part handler provides the behavior. When bound together, they form an ed
  287. itable segment of a document.
  288. Part handlers are dynamically linked into the run-time world of the document, based on the part types that appear in the document. Because any sort of part might appear in any document at any time, the part handlers must be dynamically linked to provide a smooth user experience.
  289. OpenDoc assumes that parts will mainly be used in a shell which allows a OpenDoc document to act like a present day application. This document shell will provide an address space, distribute events, and provide basic UI resources like windows and menus. 
  290.  
  291. Editors and viewers
  292. OpenDoc further breaks down the notion of part handlers into two concepts: part editors and part viewers. The difference between the two is that part viewers do not provide editing capability, but do provide full rendering and storage management. It is recommended that developers eventually create both kinds of handler for any given piece of content. The editor would be sold at an appropriate price, but the viewer could be freely distributable. 
  293.  
  294. Events
  295. Because one of the major aspects of OpenDoc is customization, OpenDoc part handlers must handle two distinct kinds of events: semantic events and UI events. The difference between the two types deals mainly with whether the event makes sense outside of the particular display context of the document. 
  296. A UI event needs information about where windows are located, how parts of the document have been scrolled, or in what part a selection was last made. These events include mouse clicks, keystrokes, and menu activations.
  297. By contrast, a semantic event deals with the semantics of the document. Generally, they are independent of the graphical context, and deal with the content model of the part. Apple events which appear in the Apple event Registry are an excellent example of semantic events.
  298. This distinction between the kinds of events yields a number of architectural advantages. OpenDoc applications are easier to script and record, but at the same time are easier to adapt to new user interface environments. OpenDoc documents and handlers are highly customizable as well, since the semantic interface allows extension or alteration of the UI without disturbing the core computational elements.
  299. In OpenDoc, both kinds of events are passed to the part handlers by a generic document shell. This document shell performs many document wide functions, and one of the primary ones is the passing of events to part handlers. Typically, this shell will be provided by the platform implementor of OpenDoc. As with all parts of OpenDoc, this document shell is replaceable.
  300.  
  301. Registration
  302. In an earlier section, we mentioned that a part handler is bound to a part based on the type of the part. To perform such a binding, a table of which handlers go with which parts must be maintained somewhere in the system. We call this table the part registry. There are a number of similar tables which are associated with areas like data translation and scripting systems. In each case, the table is used by a binding mechanism to choose the proper code to execute a task.
  303. In considering how to perform registration and binding, we considered two fundamental aspects: user preference and document stability. Both are fundamentally user experience issues. The user wants documents to remain stable in content and behavior no matter where they are moved. At the same time, the user wants his or her chosen set of part handlers to remain stable as well. This is a fundamental tension, and we resolve it by providing a series of behaviors which we feel provide a good mix of both desired responses.
  304.  
  305. Storage
  306. Storage is a major issue in OpenDoc. Given the presence of multi-part documents, a persistent storage mechanism must be created which enables multiple part handlers to share a single document file effectively.
  307. OpenDoc assumes that such a storage system can effectively give each part its own storage stream, and that reliable references can be made from one such stream to another. Because many pieces of code may need to access a given part, the storage system must support a robust annotation mechanism to allow information to be associated with a part without disturbing its format.
  308.  
  309. Run-time
  310. At run-time, OpenDoc assumes that an instance of the document shell will be created for each document. This generic shell will be responsible for providing four basic structures to the part handlers. These are: the storage system, the window and its associated state, the event dispatcher, and an arbitration registry to allow negotiation about shared resources like the menu bar.
  311. On the Macintosh, the run-time shell of a OpenDoc document will also be responsible for binding and loading part handlers for the parts which appear in the document. It is assumed that once a given part handler is loaded, any part in any document may share the part handler's executable code.
  312.  
  313. Layout
  314. Once several parts are competing for space on the display or the printed page, layout can become complex and difficult. As a result, OpenDoc defines a concept called a frame to regularize the negotiation between parts for space.
  315. Frames form the basis by which documents are composed from smaller parts. The structure of the frames provides information about layout, containment, and document context. 
  316.  
  317. Customization
  318. Another major goal of OpenDoc is to increase the level of customization that a user can apply to his documents or applications. To achieve this goal, OpenDoc includes a notion of pervasive scripting and a notion of compound user interface.
  319.  
  320. Scripting
  321. Content centered scripting
  322. OpenDoc includes a notion of content centered scripting. By this, we mean scripting based on the content model of parts. To be scriptable, a part handler must have a content model, with its constituent lists of content objects and operations. The OpenDoc model assumes a method of delivering semantic events from a scripting system to part handlers, which respond to the events. Apple events is an example of such a system.
  323. To reach higher levels of scripting support, more support is needed from the part handler. There are a series of possible options: simple scriptability as described above, tinkerability, and recordability. Each kind of support provides useful features, at some implementation cost.
  324.  
  325. Compound document scripting
  326. OpenDoc allows the scripting of compound documents. By specifying a naming scheme that can span part boundaries, the user can navigate to the content object in question using familiar document structures. Any part of any document visible on the network can be scripted transparently. A given semantic event, however, cannot act in more than one part at a time.
  327.  
  328. Compound UI
  329. OpenDoc supports a notion of compound user interfaces. This means that one can use OpenDoc parts to build user interface elements like dialogs, tool palettes, tool ribbons, and menus. By using scripting to let these UI elements and the part handlers communicate, end users or in-house development shops can alter or extend the graphical interface of the part handlers they purchase.
  330. This capability is allowed, but not implemented, by OpenDoc. A future project may provide the foundation for creating this kind of user interface in conjunction with OpenDoc.
  331.  
  332. Collaboration
  333. Collaboration takes many forms in OpenDoc. The word collaboration means many things to many people. It may mean working together on the same content, or exchanging information between differing content environments.
  334. OpenDoc provides recipes that enable the other kind of collaboration, that of exchanging information between OpenDoc documents programmatically. Lastly, OpenDoc provides mechanisms that allow users to collaborate safely, protected from malicious or accidental alteration of their information.
  335.  
  336. Mail
  337. One advantage of OpenDoc is the separation of part handlers from document level functions. This places Apple and other platform vendors in an excellent position to add new features to documents without asking developers to revise their applications. OpenDoc's document shell thus provides the access to platform mail facilities, particularly mail sending, without developer interaction. However, part handlers with knowledge of specialized mail or messaging systems will still be free to implement features based on those systems.
  338.  
  339. Collaboration between parts
  340. OpenDoc allows for collaboration between parts using scripting. Scripting forms a rich medium for coordinating the work of parts in documents, and allows users and parts to work together to perform tasks. By extending scripting to use messaging services as well as direct calls between applications, collaboration over time or space becomes available to smart documents as well as users.
  341. In addition, OpenDoc supports a notion of extended interfaces between parts. These interfaces extend the basic OpenDoc interoperability layer with specific added functions which developers can use to increase collaboration between parts.
  342.  
  343. Shared documents
  344. Another major area of collaboration is the shared creation of documents. OpenDoc places great emphasis on enabling users to collaborate through a mechanism familiar to many people: drafts of a document.
  345. When multiple users share a document, each can work in his own draft, which can be reconciled manually with other user's drafts at a later time. Users can look back through the drafts of the document they and others have created.
  346. Drafts are document-wide, and store only those parts of a document that have changed in each draft. As a result, it will be practical for users to store several drafts in a document without prohibitive space overhead.
  347.  
  348. Document interchange
  349. Needless to say, when people are sharing documents, the issue of data translation will arise. OpenDoc provides access to translation in a number of areas: clipboard transfers, document transfers, messaging, and part instantiation. 
  350. When people are sharing documents, data integrity becomes a major issue in a component world. If users have different part handlers for the same parts, subtle difficulties can arise as data is passed back and forth between users and their machines. Differences in display geometry, indexing schemes, or I/O implementations can cause slight but annoying differences.
  351. OpenDoc helps solve this problem, again using the idea of drafts. If translation occurs in the process of sharing documents, the user can always consult an older draft to regain access to formatting information that might have been lost during document translation. OpenDoc documents can support multiple representations of translated documents.
  352. Another aspect of maintaining data integrity is the promotion of standard formats for publishing a variety of different kind of content. OpenDoc provides a strong foundation on which these standards can be built. By providing a basic usage model for compound documents, OpenDoc enables content formats designed to work well in compound documents with extensive embedding.
  353.  
  354. Cross-platform
  355. OpenDoc is an architecture which is intended to span platforms. We have, therefore, attempted to capture our assumptions about which platform features must exist, and what constraints are placed on their operation. 
  356. We have attempted to make our APIs general enough to adapt to most platform human interface and runtime models. We attempted to consider Macintosh, Microsoft Windows, Motif, OPEN LOOK, and OS/2 when considering how to build OpenDoc.
  357. Issues of data integrity are also critical in cross-platform settings. OpenDoc will be promoted by an organization devoted to solving these issues in a vendor-neutral fashion. This 
  358. organization, the Component Integration Laboratories (CIL), is composed of a number of platform and application vendors with a common interest in solving these issues.
  359.  
  360. Chapter 2. Class Library
  361. OpenDoc is a cross-platform architecture for compound documents which can be used collaboratively, and can be scripted. This chapter provides an introduction to the classes implemented in OpenDoc's libraries, and the design goals behind them. 
  362. OpenDoc is built as an object-oriented system, but is designed to allow procedural code to be easily plugged into its overall structures. A key design goal was to allow existing applications to be retrofitted easily to work in an OpenDoc environment. Another design goal, that of replaceability, makes OpenDoc a level playing field on which many developers, at both the system and application levels, can innovate. Lastly, the system is extensible to assure a long lifespan.
  363. This document does not describe the operation of the classes in detail, nor does it attempt to convey a sense of how the overall architecture was designed. Instead, it describes the class structure and object interactions of the first release of OpenDoc technology.
  364.  
  365. Design goals
  366. Cross-platform
  367. OpenDoc is designed to be a cross-platform architecture, easily adaptable to any platform both in terms of runtime model and human interface specification. It makes very few assumptions about the underlying platform.
  368. Its primary assumptions are the following: 
  369.      There is an event based graphical user interface model for the platform.
  370.      There is a method of dispatching messages between separately compiled executables. For encapsulation reasons, we express the boundaries between executables in terms of objects and methods.
  371.      There is a persistent storage system with stream  based I/O available.
  372.  
  373. Easy Retrofit
  374. OpenDoc is designed to have existing code moved into it in as easy a fashion as possible. Thus, the design attempts to specify as little as possible about the internals of part handlers, the equivalent of existing applications in the OpenDoc world.
  375.   Memory recovery model does not specify a particular allocation model or memory management scheme.
  376.   I/O subsystem provides stream storage interface, and does not require a particular language or object format.
  377.   Imaging subsystem does not require any particular drawing library, and attempts to constrain the drawing as little as possible.
  378.   Event handling is designed to be as close to existing systems as possible, and includes support for modal behavior as well as edit-in place behavior.
  379.  
  380. Replaceable
  381. OpenDoc is designed for its various sub-sections to be replaced by platform vendors as well as other software developers. To achieve this, we take several precautions:
  382.      OpenDoc objects do not expose data members to outside view or manipulation.
  383.      We define groups of objects which may be implemented as a set, called cliques. Cliques of objects often have private interactions amongst their members which are not publicly available. A clique must also have the characteristic that members of the clique are instantiated under the control of other members of the clique, except for a single master object class. One should not implement private interfaces which are used beyond the boundaries of a clique. Every sub-system of OpenDoc is, by definition, a clique. However, in some cases, particular sets of objects within a sub-system are also defined as cliques.
  384.  
  385. Extensible
  386. OpenDoc does not cover the entire space of possible component interactions. Far from it, it instead concentrates on human interface interactions such as event handling, scripting, and layout. However, we realize that it's quite likely that others will wish to extend the interaction space by adding new methods to the classes involved. We formalize this as follows:
  387.      Every significant class has an extension mechanism built-in, which allows clients of the object to ask for named extensions. 
  388.      It is always allowable for a class to refuse to give a client access to an extension.
  389.  
  390. Not a framework
  391. While OpenDoc is designed as a set of interacting objects, it is not an object-oriented framework in  the traditional sense of the word. Specifically, the purpose of OpenDoc's design is not to make it as simple as possible to create compound documents, but merely to make it possible. This means that we concentrate on distribution of the necessary information, not enforcing consistency of interface or implementation.
  392.  
  393. Sub-systems
  394. OpenDoc can be considered as a series of sub-systems, designed for easy replacement. Each sub-system has a set of associated classes, although some classes could be considered members of more than one sub-system. Nonetheless, the sub-systems are a good way to conceptualize the system at a high level. The sub-systems are: Shell, Storage, Imaging, HI Events, and Semantic Events.
  395.  
  396. Shell
  397. The outermost sub-system, and by far the most platform-specific, is the shell. This system is not specified as a part of the basic OpenDoc design because its process model and human interface are very platform-specific. The shell is responsible for providing the process in which the Session object resides. It is also the focus of human interface interaction for the document.
  398. The shell's basic responsibilities are to:
  399.      Create and initialize the Session object and its direct contents.
  400.      Open the appropriate document  (as instructed by the user using the platform human interface) from  the storage system.
  401.      Accept human interface events and pass them to the OpenDoc Dispatcher.
  402.  
  403. Storage
  404. The storage system is the place where persistent storage is managed by OpenDoc. It is not an object-oriented database, but is instead a system of structured files, each of which contains many streams. It was designed this way to ease the transition for developers working with existing code bases, which generally assume stream based I/O.
  405. The primary object here is the StorageSystem object, which instantiates and maintains a list of Container objects. Each Container may contain a number of Document objects, each of which contains one or more Draft objects. Each Draft contains a number of StorageUnits, which are much like a directory structure in an existing file system. Every StorageUnit can be thought of as a list of properties, each of which has a number of streams called values. There can be several values for any property, and values are distinguished by type.
  406.  
  407.  
  408. Here's a diagram of the contents of a storage unit, as well as a simple example:
  409.  
  410. Okay, now here's an example of a StorageUnit in use. It is not a complete description, but serves to illustrate the use of a storage unit. This particular storage unit contains a bit of word processing content. The part involved is storing a name property as well as the contents property, where the primary information about the part is stored. This particular storage unit has a single representation of the name property, but has saved three representations of the contents property: a MacWrite II format, and RTF format, and a PICT format.
  411.  
  412. A storage unit can have persistent references to any other storage unit, stored in any of its values. This means that storage units can be arranged in many different organizing schemes.  One typical organization is a hierarchy, and in fact this is how OpenDoc stores its embedding hierarchy within a document.
  413.  
  414. Also associated with the storage system are objects to support linking, the clipboard, and a drag & drop interface. Each of these classes makes a storage unit available for storing data to these data transfer mechanisms. In turn, each of the storage units is associated with a full draft for storing compound information.
  415.  
  416. Each of these data transfer objects also has specific methods associated with its particular mode of data transfer.
  417. Lastly, a pair of handy objects for referring to particular locations within a storage unit: StorageUnitView and StorageUnitCursor, provide easy and reliable access to particular values within a storage unit. 
  418.  
  419. Imaging
  420. The imaging subsystem is really a geometry subsystem, not a full imaging model. Its purpose is to provide a repository and protocol for describing part geometry in a document, whether for printing or window display.
  421.  
  422. The system derives geometry from three primitive notions, the implementations of which are platform specific. These are:
  423.      Canvas: a drawing context which supplies a color table, coordinate space, etc.
  424.      Shape: a description of a geometric area of a Canvas. In QuickDraw, this would be a region plus a 32 bit offset.
  425.      Transform: a geometric transformation specific to the drawing system. For QuickDraw classic, this would be a simple offset. In more complex systems, such as QuickDraw GX, a full 3x3 matrix is a likely representation.
  426. The actual process of imaging is not addressed by OpenDoc. That is to say, we do not have a part of the API which actually draws lines, circles, bitmaps, etc. Instead, we expect the part handler to make the appropriate calls based on the kind of Canvas onto which they are drawing.
  427. Window State is merely a list of windows in which OpenDoc parts are displayed. The Window class represents a platform specific window, and holds a Layout object which specifies the relationship between various part Frames in that particular window.
  428. The Layout class, just mentioned, handles the  structure of a graphical layout. It holds containment and z-ordering information about a set of part frames. This data structure can be used to lay out a window's contents, or to lay out contents on any drawing canvas. Thus, the same Layout object can be used for printing as well as active display. To handle the difference between layout to a static device like a printer and an active device like a computer display, a flag is stored in the Canvas object associated with each layout.
  429. The Frame objects contained within a layout are data structures designed to store geometry information resulting from interaction between a containing part and the embedded part being displayed in the frame. The frame handles update notifications and acts as a repository of geometric information.
  430. Typically, during the imaging process, a part handler is asked to draw a particular Frame. The part handler gets the clipping, transformation, and layout information from the Frame, and then calls the desired graphics toolbox calls to perform the actual drawing.
  431.  
  432. HI Events
  433. HI events are handled by two primary objects, the Dispatcher and the Arbitrator. Together, these classes deliver events to the appropriate part handler.
  434. The Dispatcher is intended to accept HI events from the underlying operating system and dispatch them to part handlers. Typically, a part handler is unconcerned with the dispatcher, and is called by it at run-time. It is a modular design, which can be extended to handle new classes of events at run-time by adding DispatchModule objects. Each of these modules is responsible for reading information stored in the Arbitrator, Window State, or similar structure and deciding which frame, with the attendant part, should be asked to handle the event. Should the chosen part be unable to handle the event, it's container can register interest in the events not handled by an embedded part.
  435. The Arbitrator is designed to arbitrate ownership of shared resources like the menu bar, keystroke stream, etc.. Like the Dispatcher, the arbitrator is modular, and can be extended to arbitrate software or hardware resources defined by part handlers or platform capabilities. The Arbitrator uses a two-phase commit scheme to avoid resource deadlocks, and can be used for distributed resources as well as local resources.
  436.  
  437. Semantic Events
  438. The Semantic events sub-system is the first of a number of extensions possible under OpenDoc. The purpose of this extension is to allow OpenDoc parts to be scripted, meaning that they can be controlled remotely to accomplish some useful task. These tasks are specified using user-level abstractions, rather than programmer level abstractions. Semantic events are not an RPC mechanism, but rather a verbally intuitive command mechanism which can be used to automate user-level tasks. Several objects are involved. 
  439. The basic process of handling semantic events is that of accepting an event and then calling the part handler to invoke the correct code. Because semantic events generally need to be synchronized with user generated events to some extent, the Dispatcher implements the code to actually process the event and dispatch it to the appropriate part.
  440. Because users must often act on lightweight objects which are presented by a part, we have designed a system for naming both lightweight and heavyweight objects. We call these names object specifiers. We also implement an object, the NameResolver, which takes object specifiers and resolves them into particular objects on which events can operate. Typically, an event arrives with one or more object specifiers, and the event handling code resolves these specifiers using the NameResolver, and then acts.
  441. Both the event handling code and the code necessary to resolve object specifiers is exposed to the other parts through an extension object called the Semantic Interface. This is mainly a repository for code which can be called by the NameResolver and the Dispatcher. 
  442. Lastly, should part handlers wish to send semantic events themselves or make them available for recording, an object called the MessageInterface allows them to send semantic events and record them.
  443. Note that the entire semantic events system is a pure extension to the basic OpenDoc system. Any object which does not publish a Semantic Interface object will not be scriptable, but will be a first-class citizen of OpenDoc in all other respects.
  444.  
  445. Class Hierarchy
  446. The existing OpenDoc class system as it might appear in a C++ specific world is shown in Figure 3.1. Later in the development cycle, this hierarchy will be replaced by a System Object Model (SOM) based hierarchy and use abstract base classes with multiple inheritance to define the behavior of objects. At present, there is little inheritance in the hierarchy and extensive use is made of delegation instead. This preserves the language-neutral flavor of OpenDoc and prepares us to use SOM  in the future.
  447. The class hierarchy diagram does not contain every class defined by OpenDoc. There are a large series of iterators which do not appear, as well as one object which represents a simple set of other objects. These objects are simple to conceptualize, and are basically support objects for classes which appear in this diagram. We have left them out to aid initial understanding. Examination of the specific class APIs should make the purpose of these objects obvious.
  448. The run-time state of an OpenDoc document, and the relationships which various OpenDoc classes have to one another is shown in Figure 3.2. The relationships generally consist of pointer references from one object to another. The labels are meant to give some human readable meaning to the pointer reference.
  449. As has already been mentioned, the inheritance hierarchy of the classes is quite flat (Figure 3.1). This is because the team chose to use delegation as much as possible for maintenance and replaceability. There are three abstract base classes, for reference counting, extension, and persistence. Conceptually, these three capabilities are orthogonal. In practice, with the existing C++ based API, all ref-counted objects are extensible, and all persistent objects are ref-counted.
  450. We will examine the classes in terms of the abstract base classes, followed by the various sub-system groupings, followed by a last category of 'service' classes, which serve as utilities for the other classes to use.
  451.  
  452. Abstract Base Classes
  453. RefCounted Objects
  454. RefCounted objects are objects which maintain a count of how many other objects refer to them. The major object classes of OpenDoc are all RefCounted, so that session global memory can be managed. Objects cannot be removed from memory unless their reference counts go to zero.
  455.  
  456. Extensible Objects
  457. Extensible objects are objects which can return extensions of themselves. These extensions are themselves objects, and are all RefCounted objects. An object which has special behavior beyond that specified by OpenDoc should make this behavior available through an extension. All subclasses of XMPObject are extensible.
  458.  
  459. Persistent Objects
  460. Persistent objects are objects which have a designated StorageUnit object which is created when these objects are added to a storage draft. A small set of very important document structure classes is derived from this base class. All persistent objects are reference counted.
  461.  
  462. Implementation Classes
  463. Storage
  464. The primary objects associated with storage are StorageSystem, Container, Document, Draft, and StorageUnit. The StorageSystem object is designed to support Container objects which have any of several different implementations. Implementation of Container, Document, Draft, or StorageUnit will probably only work with other objects which were implemented as a clique. The Container class serves as the master object of the clique, since once a container is instantiated all of the documents, drafts, and so on are created by a member of the clique. 
  465. The data interchange objects: Link, Drag & Drop, and Clipboard, should be replaced as a clique along with whatever storage implementation they will be using.
  466.  
  467. Imaging
  468. Canvas, Shape, and Transform are designed as a clique. Thus, they should be implemented together and should also handle translating between any graphics models specified by the platform implementor.
  469. WindowState, Window, Frame and Layout are also a clique, and should be replaced together.
  470.  
  471. HI Events
  472. The Arbitrator and Dispatcher are generally not replaced, and are designed to have their specific behavior code modularly replaced. Thus, there is no particular notion of clique membership involved in altering their behavior. However, there is some semantic event interaction with the Dispatcher, as noted in the following section.
  473.  
  474. Semantic Events
  475. The NameResolver, SemanticInterface, MessageInterface, and the Dispatcher module associated with scripting events or synchronization between script execution and HI events should be replaced as a clique.
  476.  
  477. Service Classes
  478. A few object classes appear mainly as services for other classes to use. The Translation object, for instance, is the API to platform specific translation services which may be available. The Symbols and Name Space classes exist to provide a handy implementation of attribute/value pair storage.
  479.  
  480. Figure 3.1 Abbreviated OpenDoc Class Hierarchy
  481.  
  482. Figure 3.2 Abbreviated OpenDoc Object Model
  483.  
  484. Chapter 3. Programmer Model
  485. This chapter is divided into four sections, each representing a particular kind of developer. They are: 
  486.  
  487. Part handler (new)
  488.     These handlers represent new development efforts, from the ground up. Many part handlers will be created this way, but many will also be produced as refits of existing application code.
  489.  
  490. Part handler (refit)
  491.     These handlers are produced by refitting existing applications to match the OpenDoc model. They are easier to produce than writing from scratch, but may have limited functionality.
  492.  
  493. Container
  494.     These are applications modified to be containers of OpenDoc parts, thus replacing the standard document shell application.
  495. Platform vendor
  496.     This is the effort needed to implement OpenDoc on a new platform.
  497. These sections tend to be a bit repetitive. It may make sense to read each of the sections independently, based on reader interest, rather than trying to wade through them in order. Many existing applications will be a combination of new implementation and refit, and so may straddle the various categories.
  498.  
  499. Programming environment
  500. OpenDoc provides a new set of facilities which programmers may use to create new user functionality. These basic facilities allow a dynamically linked part handler to coexist with other handlers in the same document space.
  501. This document space is called the OpenDoc document shell. Really, it is a special version of the traditional application. It provides a shared address space which the handlers can use to internalize document content. At the same time, it provides a set of global databases which handlers can use to track the behavior of the document and other handlers.
  502. Here's an illustration of these global structures. This picture is not an exhaustive description, but gives a sense of the most important structures.
  503.  
  504. The various global structures are:
  505. Storage
  506.     This set of objects manages the persistent storage of the document, as well as providing memory management of the ephemeral storage required by the part handlers.
  507.  
  508. Dispatching
  509.     This set of objects is responsible for delivering both semantic and UI events to the part handlers.
  510.  
  511. Arbitration
  512.     These objects manage shared resources like the menubar, keystroke focus, etc.
  513.  
  514. Window state
  515.     These objects manage the visible windows and their associated frames, so that handlers can cooperate to lay out graphics into the windows.
  516.  
  517. Undo
  518.     These objects allow undo and redo to be coordinated in the document.
  519.  
  520. Clipboard, Drag & Drop
  521.     These objects make it easier to transfer information between handlers.
  522. Into this space are linked the part handlers which replace applications in OpenDoc. Each part handler is bound at run-time to the part information stored persistently in the document file.
  523.  
  524. Part Handler (new from scratch)
  525. Produce content model
  526. Developers must create a content model and construct semantic events which allow a full range of operations on the objects in their content model. 
  527.  
  528. Implement core data engine
  529. In any program which does useful work, there are a set of data structures which are manipulated according to some set of rules. It may or may not persistently store information, but in all cases data are manipulated according to some set of algorithms. We refer to this set of structures and rules, independent of any human interface, as the core data engine or core engine of a program.
  530. While this is an obvious step, there is little to say from the OpenDoc point of view about how this is accomplished. It is clear that the engine should be able to free storage when requested, and should adequately handle cases where the part can only be partially read, handle any multiprocessing issues, etc.
  531. A key element of this process, if script recordability is desired, is to make sure that the human interface interacts with the core engine through a restricted set of calls which match the user model of the core engine. These calls, which we term semantic events, are generally not useful as a high-bandwidth API to the core engine, but instead a user interface building toolkit. Given a bottleneck through which these semantic events pass, scripts can be recorded with robust, high quality semantic content.
  532.  
  533. Implement storage code
  534. Basic storage of the part
  535. To guarantee the collaborative aspects of OpenDoc it is necessary for the part handlers to utilize the Storage API and store the applicable standard properties with every part that they create or edit.
  536. The part handler is responsible for implementing code to internalize and externalize the part. This need not mean a complete load into memory, nor a complete rewrite of the part content. However, the handler must be able to get the part into a workable state for accepting events and rendering requests, and it must be able to guarantee that the part has been satisfactorily written to the structured storage system. The part handler should never change the type of the part without an explicit user action. Any translations which must be done automatically will have been performed by the platform implementation.
  537. The part handler implementor is also responsible for managing segmentation of his part handler, which is linked as a shared library. Lastly, he is responsible for managing global storage associated with the handler, as opposed to any particular part. 
  538. The developer view of the storage facility is quite different from the current file system and resource manager, but the change in viewpoint is necessary to enable the compound document features of OpenDoc.
  539.  
  540. Data transfer
  541. Both the clipboard and drag & drop represent ways to transfer information between parts. OpenDoc supports the movement of compound data by providing the same storage abstraction for data transfer that is used for persistent storage. Thus, the clipboard and drag packages are represented as storage units, with an associated draft.
  542. A slight addition is the notion of a promise, a special clipboard type which represents a promise of information which will later be forthcoming.
  543.  
  544. Linking
  545. Linking support is really a combination of event handling code and storage code. Linking uses the same data transfer mechanisms mentioned above. However, XMPLink adds a set of notification calls which keep the destination of a link up to date. This mechanism can hide publish & subscribe as well as intra-document links.
  546.  
  547. Collaboration and drafts
  548. Developers should not have to worry about drafts of OpenDoc documents normally. The document shell will handle the mundane aspects of drafts for the developer. 
  549.  
  550. Implement rendering code
  551. During rendering, the part handler is responsible for examining the frame and displaying the correct information, properly transformed and clipped, in the frame. The part handler is responsible for storing any needed information in the part info field of the frame.
  552. The part handler should examine the frame to determine whether the frame is on a dynamic canvas or a static one, and perform frame negotiation accordingly. On a static canvas, the frame should attempt to add frames or extend them until all of its contents have become visible. On a dynamic one, assuming the part allows scrolling, it need only live with whatever frame the containing part offers.
  553. If, during rendering, the part handler must get an embedded frame to render, it is responsible for adding that frame to the layout data structure.
  554. If the embedded frame moves or is no longer visible, the embedding part handler is responsible for updating the layout or removing the frame from the layout.
  555. If the part handler has more than one frame in which it is displayed, it is responsible for determining which of its frames are visible and updating those frames if an alteration is made in the part in response to some event. This may include invoking frame negotiations.
  556.  
  557. Implement event handling code
  558. Having implemented a content model and semantic event handling, the developer must support direct manipulation of the part by implementing those routines of the part API which respond to UI events like mouse clicks and keystrokes. In addition to tracking the mouse and dealing with Drag-And-Drop, the part handler may take the appropriate steps to support scripting.
  559. Part handlers must also implement the portions of the API which respond to activation and deactivation, by modifying the layout and configuration of the user interface. Part handlers must use the OpenDoc arbitrator API to manipulate the menu bar. If the remainder of a part's user interface can be contained within its frame, or in floating windows, existing code might port fairly easily. But part handlers might wish to display UI elements like rulers outside of the active frame, in which case they are getting involved in layout negotiation. Developers might also wish to switch to using OpenDoc UI parts rather than lower-level facilities.
  560. There is a mechanism for extensions to the part API, so that the minimal API can be kept small. A part with a simple content model and a minimal direct manipulation interface should be easy to implement.
  561.  
  562. Implement scripting code
  563. Part implementors who choose to support the semantic events extension must implement code to handle the semantic events defined in their content model.
  564. Forward-thinking developers who already support AppleEvents and AppleScript will have done much of this work already.
  565. Part handlers must provide accessor functions to resolve external references to a part's content objects. They must also provide semantic event handlers to implement their content operations. Part handlers must record which selections are exported as links, and notify dependent parts when linked content objects change.
  566. By investing the effort in developing a content model, and implementing the routines for resolving object specifiers and handling semantic events, the developer of a part handler has ensured the separation of the part handler's 'engine' from its user interface, and will reap great rewards. The part type is editable by all future interfaces which generate semantic events, including script, voice and pen interfaces. More mundane interfaces like menus and dialogs, built using state-of-the-art tools, can also invoke scripts or otherwise generate semantic events.
  567. In order to allow script recording, the developer must generate and process semantic events as a result of any UI event, and process the semantic events through a standard bottleneck where a recorder may record the events. Note that this is also a good way to get ready to support new human interfaces like pen and voice recognition, and greatly enhances portability. Recording for its own sake may not be important enough to induce developers to follow a strict separation of UI and semantics, but the added bonus of better interfaces and portability probably makes this a good option.
  568. To allow tinkering, a developer creates a scriptable and optionally recordable application. Before processing an event, the part handler must check to see if a script attached to the part wants to handle the event. If so, it must allow the script to run.
  569. The part handler, if made scriptable, might activate UI part handlers for the menu bar, tool palettes and ribbons, and dialogs, rather than implementing these internally. Those UI part handlers invoke scripts that talk back to the original part and part handler that invoked them.
  570.  
  571. Implement desired extension interfaces
  572. The part handler is responsible for implementing any desired extension APIs. These may cover any of a number of areas, and detailed descriptions are beyond the scope of this document. These could include full text search, spell checking, linking, or many other possible interactions. In general, these APIs are reserved for those areas whose bandwidth or integration requirements deny the use of scripting to accomplish the interaction.
  573. The CIL will be actively involved in proposing and publishing standard interfaces between parts.
  574.  
  575. Package the part handler
  576. The developer, as part of packaging the part for shipment, should attach information indicating what part types are handled, what semantic events are handled, and what extension APIs are handled. 
  577.  
  578. Create stationery
  579. Once a working part handler is available, the developer will need to produce some stationery which has an empty copy of his part type. This stationery will be used by end users to insert new parts of the correct type.
  580.  
  581. Additional steps if writing a containing part handler
  582. Add embedded parts to content model
  583. A named object type of the content model of any containing part, where embedded parts can be added, must be defined.
  584.  
  585. Add frame management to event handling code
  586. Once embedded parts are present, any event handling code which changes a frame will need to include code to notify the part in the frame of the change, and code to maintain the shape and transformations of the frame itself.
  587. If, during rendering, the part handler must get an embedded frame to render, it is responsible for adding that frame to the layout data structure, and asking the frame to render itself.
  588. If the embedded frame moves or is no longer visible, the embedding part handler is responsible for updating the layout or removing the frame from the layout.
  589.  
  590. Add frame management to rendering code
  591. Rendering code in a containing part must include layout negotiation support, and must update the transformations associated with each visible embedded frame.
  592.  
  593. Add embedding support to storage code
  594. For the containing part, this is relatively simple. If it wishes to write out an embedded part, it can simply ask that the storage unit be copied to the new location, and the OpenDoc libraries will take care of the data copying.
  595.  
  596. Part Handler (refit existing application)
  597. Determine content model
  598. Existing applications, which do not have a defined content model, may have to retroactively determine one. This process is necessary only if linking or semantic events are to be supported by the part handler.
  599. In general, this process is one of examining application behavior and abstractions to come up with a content model.
  600.  
  601. Factor core data engine
  602. Again, if scripting is to be supported, particularly tinkerability and recordability, the application code must be factored into a core data processing engine, driven by semantic events, and a presentation driven by HI events. Once this factoring has taken place, the application is ready to have scripting code fitted onto it.
  603.  
  604. Refit storage code
  605. Because OpenDoc part handlers must share persistent storage, it is necessary to refit any file I/O or clipboard I/O into OpenDoc terms. This is generally very simple. The Handler need only know the correct property name and have a defined value type to read and write into an OpenDoc value stream. The remaining code, assuming it is stream oriented as most applications are, can simply be used with the OpenDoc read and write calls.
  606.  
  607. Refit rendering code
  608. Because OpenDoc layout is shared, a part must refit its rendering code to handle existence in an OpenDoc frame. Again, this is straightforward if the code already uses the platform window clipping tools. 
  609. Beyond this simple clipping change, the part must also make decisions about how it wants to respond to changes in its enclosing frame. The simplest decision is to simply clip to whatever size is given. However, scaling to fit, attempting to resize or asking for added frames are also options, to be decided based on user requirements.
  610.  
  611. Refit event handling code
  612. The event handling refit is probably the most serious step besides scripting support. The developer must change his code to handle the menu bars, palettes, and dialogs to match the OpenDoc model. In general, this involves testing for activity (whether the part already has the needed foci) and grabbing menu, keystroke, and selection focus as needed.
  613. Once these are obtained, the part is free to put up dialog boxes, change the menu bar, or put up palettes as needed. When focus is lost, the part handler should remember the fact and hide windows or palettes, and also get ready to reacquire foci if needed later.
  614.  
  615. Refit scripting code
  616. Once the basics of scripting: content model and factoring have been defined, the rest of it is relatively easy. Installing event handlers and object accessors is very similar to the process for doing so in a normal application. Assuming that the applications is already using the AppleEvents and the open scripting architecture, most of these will have already been completed by the developer. In OpenDoc, the SemanticInterface object is the location for installation, instead of using the normal Apple Event Manager call. For sending events, the MessageInterface is used instead of the AE Manager.
  617.  
  618. Container
  619. It will be very useful to refit large existing applications to be part containers. These documents will still be owned by their application, but that application will be reworked to add OpenDoc parts embedded in their content.
  620. This task is not trivial, but is in fact relatively simple. It is more difficult than the QuickTime revision, but can probably be accomplished with a week or two of programmer time.
  621.  
  622. Add some initialization code
  623. A container only application will need to call the same initialization call to the OpenDoc libraries that the document shell application would normally call.
  624.  
  625. Refit storage code
  626. Because OpenDoc part handlers must share persistent storage, it is necessary to refit any file I/O or clipboard I/O into OpenDoc terms. This is generally very simple. The Handler need only know the correct property name and have a defined value type to read and write into an OpenDoc value stream. The remaining code, assuming it is stream oriented as most applications are, can simply be used with the OpenDoc read and write calls.
  627. Thus, the application must still be willing to use the OpenDoc file format for files that contain parts. The application will be given a special property at the document level which it can use for stream oriented file I/O. We will provide a small library with an appropriate routine to return an XMPStorageUnitView which the container can use for writes and reads.
  628. All embedded parts can then use the ordinary storage system calls, without interfering with the document.
  629.  
  630. Refit event handling code
  631. The document will then need to handle events by passing events to the OpenDoc dispatcher first, and handling them only if OpenDoc does not.
  632. To accomplish this, we will define a simple "do nothing" part handler for the root frame of every container window. We'll provide a simple library call to create a window with this part handler to work with OpenDoc. This "do nothing" handler will grab mouse, selection, and menu foci (possibly others) when mouse clicks land in the container's space, and will then simply respond that the event was not handled, giving the containing application a chance to do it.
  633.  
  634. Add embedded parts to content model
  635. A named object type of the content model of the container, where embedded parts can be added, must be defined.
  636.  
  637. Add frame management to event handling code
  638. Once embedded parts are present, any event handling code which changes a frame will need to include code to notify the part in the frame of the change, and code to maintain the shape and transformations of the frame itself.
  639. If, during rendering, the container must get an embedded frame to render, it is responsible for adding that frame to the layout data structure, and asking the frame to render itself.
  640. If the embedded frame moves or is no longer visible, the container is responsible for updating the layout or removing the frame from the layout.
  641.  
  642. Add frame management to rendering code
  643. Rendering code in a containing part must include layout negotiation support, and must update the transformations associated with each visible embedded frame. This includes printing code.
  644.  
  645. Add embedding support to storage code
  646. For the container, this is relatively simple. If it wishes to write out an embedded part, it can simply ask that the storage unit be copied to the new location, and the OpenDoc libraries will take care of the data copying.
  647. This means that the container should probably use OpenDoc calls to write to the clipboard or drag & drop.
  648.  
  649. Platform Vendor
  650. Implement a storage system
  651. The platform vendor is responsible for implementing the storage protocol between part handlers and the document shell. Since the document shell is the true owner of the document file, it will need to implement all of the necessary code to apply OpenDoc policies atop the structured storage facility of the platform for which the document shell is being written.
  652. Classes XMPStorage, XMPContainer, XMPDocument, XMPDraft, XMPClipboard, XMPStorageUnit, XMPStorageUnitCursor, XMPStorageUnitView, XMPLink and XMPDragAndDrop, along with their attendant iterators must be implemented. It is quite possible, even likely, that more than one implementation of XMPContainer, XMPDocument, XMPDraft, and XMPStorageUnit will exist on a platform.
  653. See the header files and class documentation in the OpenDoc API Description for detailed specifications.
  654.  
  655. Implement an arbitrator
  656. The platform vendor must implement any HI or OS policies needed to make a complete arbitrator instantiation.
  657. Class XMPArbitrator, along with its auxiliary classes and iterators, will need to be implemented.
  658. See the header files and class documentation OpenDoc API Description for detailed specifications.
  659.  
  660. Implement event delivery
  661. The platform implementor implements the delivery of events to the individual part handlers. It must accept both semantic events and UI events and deliver them correctly to the part handlers.
  662. Classes XMPDispatcher, XMPUndo, XMPMessageInterface, XMPNameResolver, XMPSemanticEvents and XMPSemanticInterface, along with their associated iterators and so on must be created.
  663. See the header files and class documentation OpenDoc API Description for detailed specifications.
  664.  
  665. Implement a window & layout system
  666. The platform implementor implements the layout structures used by parts during layout for screen or printing. OpenDoc relies on platform facilities to perform drawing, provide coordinate spaces for layout, and all other graphical tasks. The platform implementor may need to alter the implementation of any of the window state and layout classes to suit a local environment.
  667. Classes XMPWindowState, XMPLayout, XMPWindow, XMPFrame, XMPCanvas, XMPTransform and their attendant iterators and such must be implemented. If two or more drawing systems reside on the platform, implementation of these classes may involve transforming shapes and points between coordinate spaces.
  668. See the header files and class documentation OpenDoc API Description for detailed specifications.
  669.  
  670. Implement a runtime environment
  671. A runtime environment must be created, with binding support, support for finding global document structures, exception handling, translations, and memory management. These structures may vary significantly from one platform to another.
  672. A basic set of them, defined in XMPSession, XMPDraft, XMPNameSpace and XMPTranslation appear likely to be common across a variety of platforms.
  673. See the header files and class documentation OpenDoc API Description for detailed specifications.
  674.  
  675. Chapter 4. OpenDoc API
  676.  
  677. Notes about Style
  678. Language Choice
  679. The OpenDoc APIs have been constructed in C++, a language chosen for its object dispatching capabilities as well as its relative portability. In later releases, these definitions will be written in a CORBA-compliant interface definition language, to support language-neutral 
  680. distributed dispatching.
  681.  
  682. Distributed operation
  683. In the interim, though, several steps have been taken to support distributed operation. 
  684. First, all major objects are instantiated by factory objects, rather than constructors. This does not apply to all objects, but generally applies to every object likely to be used remotely.
  685. Secondly, we have attempted to minimize the frequency of inter-part calls. In some cases, like layout, frequent calls cannot be avoided. However, in general the number of inter-part and library calls has been kept as small as possible.
  686.  
  687. PlfmType.h
  688. This file indicates the list of platform specific types used by OpenDoc's platform implementations and platform facilities. It is used to segregate these types from those defined to support common implementations. Each of these types should be redefined on each platform.
  689.  
  690. XMPTypes.h, XMPTypes.r
  691. These files include types which are used in common implementations as well as platform implementations. In general, types in these files should not be changed across platforms. Note that many types defined here depend on platform specific types, which should be changed for each platform.
  692.  
  693. Exception handling
  694. OpenDoc includes an exception handling system similar to the one proposed for C++. However, the OpenDoc implementation does not use the storage management or multiple signal types capability of the proposed standard. This allows us to produce C bindings for the OpenDoc Part API. In the future, this will be altered to match the CORBA standard for exception handling.
  695.  
  696. Class information
  697. Of primary interest to the reviewer will be the theory of operation section and the comments attached to each member of the class definitions; please refer to the OpenDoc API Description.
  698. In certain cases, the APIs are Macintosh specific, because we are evaluating their workability first on Macintosh, the platform most familiar to the team. We are especially interested in hearing about places where we have made the interfaces too Macintosh specific.
  699.  
  700. Class categories
  701. For the purposes of this document, we've divided the classes up into four major groupings, each of which we'll explain in greater detail later. These include:
  702. Developer implementations: These classes must be supplied by developers. They are typically part handlers which manage some sort of useful content, such as text editors, graphics packages, etc.
  703. Platform facilities: simple cover classes which provide handy pointers to basic platform systems like the drawing engine.
  704. Platform implementations: Classes which are highly dependent on platform specifics, but which should provide extremely similar APIs across platforms.
  705. Common implementations: These are classes which are almost independent of platform specifics in their implementation. They may be replaced by any platform implementor, but we believe extensive changes are unlikely.
  706.  
  707. Developer implementations
  708. Developers implement these classes. In fact, the vast majority of an OpenDoc document's behavior is encapsulated in these classes.
  709.  
  710. Part
  711. This class is the basic set of entry points which must be defined for any part editor or viewer. This is the major learning curve for developers.
  712. Each developer will produce a class derived from part. We will provide as much basic implementation as we can to allow a part to behave properly, but in general the developer will have about  50 calls to implement. Of these, most are related to event handling, with relatively few related to storage issues and layout negotiation.
  713. Developers who implement a part which can embed others must extend the behavior of part to include negotiation about the position and shape of embedded frames, and about their visibility.
  714.  
  715. Dispatch Module
  716. In certain special cases, a developer may wish to gain access to low level operating system events which are not covered by the OpenDoc API. In these cases, the developer will probably wish to define a new focus in the arbitrator, and deliver this class of events to the owner of that focus. To get these events delivered, the developer will need to extend the dispatcher using a dispatch module. Such modules may need to examine the arbitrator or window state to decide which part should receive the event.
  717.  
  718. Platform facilities
  719. These classes encapsulate extremely platform specific implementations. These classes are so completely specific that the class definitions are simply cover APIs, with no significant level of implementation in the reference release.
  720.  
  721. Canvas
  722. This class represents a black-box encapsulator of the basic platform's drawing environment. This represents a grafport on a Macintosh using QuickDraw Classic, but might be any of several other drawing context structures on other platforms.
  723.  
  724. Shape
  725. This class is a black-box encapsulation of the basic clipping shape structure. On Mac or Windows, this might be a region. On other systems, it might be a path or even more sophisticated structure. On less capable systems, these might be simple rectangles or rectangle sets.
  726.  
  727. Transformation
  728. A black-box encapsulation of the basic viewing transformations available on the platform. These transformations must be composable and invertable, but we use no other operations in OpenDoc.
  729.  
  730. Platform implementations
  731. These classes must be developed by platform vendors. They are in general quite platform-specific. The platform vendor must produce an implementation which closely matches the reference release in semantics, using platform specific facilities.
  732.  
  733. Iterators
  734. OpenDoc defines a number of iterator classes. These are fairly standard members of the breed. On some platforms, these implementations will need to be process/thread safe, but on others they will need no such protection. It is up to the platform implementors to make sure these iterators and the collections they iterate over are appropriate for the platform.
  735.  
  736. Arbitrator
  737. The arbitrator is used to allow parts to negotiate about shared resources. Some examples of these might include the keystroke focus, the menu bar, serial ports, or any of a wide array of other resources. Each of these resources is termed a focus, and different platforms will support differing foci.
  738. Another area in which platform specific work will need to be done is in implementing the specific behavior associated with various foci. On the Macintosh, for instance, the serial ports are shared across processes, so the arbitrator will need to globally manage serial port access.
  739.  
  740. Dispatcher
  741. This class is used to correctly distribute user interface and other low-level operating system events to the parts of the document. 
  742. The dispatcher is different on each platform, because it encapsulates many platform-specific HI rules. Platforms vary widely with respect to keyboard events, for instance. Some associate keystroke delivery with cursor position, some with a insertion focus. The dispatcher must implement all of the platform's basic HI rules when determining where events are to be sent.
  743. If needed, the dispatcher can be extended using dispatch modules, mentioned below as a developer implementation. However, a platform implementor will probably also use the dispatch module to extend the dispatcher as the platform evolves.
  744.  
  745. Storage
  746. The storage object manages access to all of the containers used by a document process. Since this class is responsible for interpreting file requests on the platform, it will almost certainly be re-implemented on each platform.
  747.  
  748. Container
  749. Containers generally represent some form of physical storage containment. However, in a sophisticated object store, the notion of physical containment may be merely illusion. In either case, the implementation of container must reflect underlying platform implementations.
  750.  
  751. Document
  752. A document represents the user concept of a document, a handy container of content. Documents serve primarily as a manager of revisions and drafts.
  753. There may be several implementations of document, depending on the kind of physical container in which the document resides.
  754.  
  755. Draft
  756. Drafts store all of the first-class persistent objects of a particular saved state in a document. A draft consists of a set of storage units, which represent both the meta-data and the actual content of a document.
  757. There may be several implementations of draft, depending on the kind of physical container in which the draft resides.
  758.  
  759. Storage Unit
  760. These represent the fundamental unit of persistent identity in a document. They consist of a list of properties, each of which is a list of values. Only storage units have persistent identity.
  761. There may be several implementations of storage unit, depending on the kind of physical container in which the storage unit resides.
  762.  
  763. Clipboard
  764. A clipboard is a data transfer structure designed to buffer data temporarily. This gives a measure of time independence to the data transfer. This same technique can also be used to give location independence to such transfers, as in the case of a network clipboard. In OpenDoc, each data transfer is conducted using a storage unit, to provide full compound content transfer capability.
  765.  
  766. Storage Unit
  767. We expect the storage unit used in a clipboard to have special, platform specific behavior. On platforms with existing clipboard mechanisms, human interface standards about what types should appear on the clipboard may exist. In these cases, the storage unit should recognize these types when they are written to the storage unit, and redundantly store them to the platform clipboard in the approved fashion.
  768. Implicit in the existence of a storage unit is the existence of a containing draft. It is in this draft that any embedded parts and frames would be transferred along with the basic data being transferred. This probably implies implementing a specialized draft class to hold this information in memory or in a specified temporary file.
  769.  
  770. Drag & Drop
  771. Drag and Drop class represents a transfer of data using direct manipulation. It is quite similar to a clipboard transfer, but is more ephemeral. In OpenDoc, each data transfer is conducted using a storage unit, to provide full compound transfer capability.
  772.  
  773. Storage Unit
  774. We expect the storage unit used in a drag & drop transaction to have special, platform specific behavior. On platforms with existing drag & drop mechanisms, human interface standards about what types should appear in the transaction may exist. In these cases, the storage unit should recognize these types when they are written to the storage unit, and redundantly store them to the platform transaction structure in the approved fashion.
  775.  
  776. Link
  777. Links represent persistent data transfer conduits. As with other OpenDoc transfer mechanisms, the data are passed using a storage unit.
  778.  
  779. Storage Unit
  780. We expect the storage unit used in a persistent link to have special, platform specific behavior. On platforms with existing linking mechanisms, human interface standards about what types should appear in the link may exist. In these cases, the storage unit should recognize these types when they are written to the storage unit, and redundantly store them to the platform link structure in the approved fashion.
  781.  
  782. Semantic Interface
  783. The semantic interface is invoked by either the document shell or the dispatcher, depending on the platform. The platform may have specific requirements around event dispatching as well, and may need to alter this class to perform the correct behavior during handler invocation. This is likely to occur if parts are accessed using interprocess calls.
  784.  
  785. Message Interface
  786. MessageInterface encapsulates the sending and reception of semantic events. As such, it is extremely likely to change from platform to platform.
  787.  
  788. Common implementations
  789. These classes are implemented by the platform vendor, just as the previous section. However, we believe these classes are so generic as to obviate the need for extensive change by a platform developer. In effect, these are provided in working form by the reference implementation.
  790.  
  791. Name Resolver
  792. Semantic events will wish to name content objects within a part. the name resolver helps parts resolve these names. Because the process of resolving names is so generic, and is specialized by developer produced callbacks, this class is unlikely to need reimplementation unless the memory management scheme is changed.
  793.  
  794. Name Space
  795. Name spaces are a generalized binding mechanism allowing association of some kind of data with a name. We plan to use this class in implementing run-time binding of part types to part handler implementation. This is a very generic process, one unlikely to need change.
  796.  
  797. Window State
  798. The window state manages the document shell's global list of visible windows. This is primarily used by the dispatcher, but may also be used by developers in creating part handlers which interact with the window system. This generic behavior is unlikely to change radically from system to system.
  799.  
  800. Window
  801. A window keeps the organization of visible frames associated with a platform window. This class keeps a black-box reference to the actual platform window. Since the window object mainly keeps lists of z-ordered frames, it is an extremely generic implementation.
  802.  
  803. Frame
  804. Frame keeps black-box references to a number of shape objects. It also provides a notification service to both the container and embedded parts associated with the frame. Again, this implementation is extremely generic. The shape and part implementations provide much of the intelligence associated with layout.
  805.  
  806. Future areas for expansion
  807. Several major areas have been planned for but not implemented in the OpenDoc architecture. Because of time and platform constraints, we have chosen not to include these features in the first OpenDoc release.
  808.  
  809. Authorization
  810. Given operating system support, we envision using the semantic interface as a bottleneck for access control and authorization. However, insufficient support exists across the desired platforms for storing and editing access information. Due to time constraints, we have chosen not to attempt to implement a common solution.
  811.  
  812. Store & forward messaging
  813. Eventually, we hope to use the same semantic interface to deliver store & forward messages as well as real-time connections. This raises a series of interface issues which have not been exhaustively analyzed at this time.
  814.  
  815. Digital signature & encryption
  816. Digital signatures of compound documents with shared data presents interface and storage issues. We believe we understand them at this time, but are not willing to implement them in this release due to time constraints and lack of consistent platform support.
  817.  
  818. Compound Human Interface
  819. The prospect of easily composed human interfaces built using parts and compound document techniques is presently handled by the architecture, but there are as yet unresolved issues about runtime support and the human interface for customizing the compound human interface.
  820.  
  821. Detailed APIs
  822. A summary of the APIs of most interest to developers is provided in Appendix A. See the OpenDoc API Description for detailed documentation and header files.
  823.  
  824. Appendix A. Public API Subset
  825. Here is a summary of the APIs most interesting to developers. This subset is not complete, and has several following sections which specify extended areas of functionality not generally of interest to developers. Calls which are italicized are Macintosh specific, and would not be a part of a reference release.
  826.  
  827. Basic part development
  828. These are the calls which a part handler developer must implement. They represent the basic development interface in OpenDoc.
  829.  
  830. XMPPart
  831. void Draw(
  832. XMPFrame* frame,
  833. XMPShape* invalidShape)
  834. XMPBoolean HandleEvent(
  835. XMPFrame* frame, 
  836. XMPEventData event)
  837. void Internalize()
  838. void Externalize()
  839. void Open(XMPFrame* frame)
  840. void UndoAction(XMPActionData actionState)
  841. void RedoAction(XMPActionData actionState)
  842. void DragEnter(
  843. XMPStorageUnit* dragInfo,
  844. XMPFrame* frame,
  845. XMPPoint whe where)d DragLeave(
  846. XMPFrame* frame,
  847. XMPPoint where)
  848. void DragWithin(
  849. XMPStorageUnit* dragInfo,
  850. XMPFrame* frame,
  851. XMPPoint where)
  852. XMPDropResult Drop(
  853. XMPStorageUnit* dropInfo, 
  854. XMPFrame* frame, 
  855. XMPPoint where)
  856. void DropCompleted(
  857. XMPPart* destPart,
  858. XMPDropResult dropResult)
  859. void FulfillPromise(XMPPtr promiseData)
  860. XMPLink* CreateLink(
  861. XMPObjectSpec* selectedContent)
  862. void LinkUpdated(XMPLink* updatedLink)
  863. XMPBoolean BeginRelinquishFocus(
  864. XMPTypeToken focus,
  865. XMPFrame* ownerFrame,
  866. XMPFrame* proposedFrame)
  867. void AbortRelinquishFocus(
  868. XMPTypeToken focus,
  869. XMPFrame* ownerFrame,
  870. XMPFrame* proposedFrame)
  871. void CommitRelinquishFocus(
  872. XMPTypeToken focus,
  873. XMPFrame* ownerFrame,
  874. XMPFrame* proposedFrame)
  875. void FocusAcquired(
  876. XMPTypeToken focus,
  877. XMPFrame* ownerFrame)
  878. void FocusLost(
  879. XMPTypeToken focus,
  880. XMPFrame* ownerFrame)
  881. void FrameShapeChanged(XMPFrame* frame)
  882. XMPShape* RequestFrameShape(
  883. XMPFrame* frame,
  884. XMPShape* frameShape)
  885. void AddDisplayFrame(
  886. XMPFrame* frame,
  887. XMPName* viewType)
  888. void RemoveDisplayFrame(XMPFrame* frame)
  889. XMPFrame* CreateEmbeddedFrame(
  890. XMPFrame* containingFrame,
  891. XMPShape* frameShape,
  892. XMPTransform* externalTransform,
  893. XMPPart* embedPart,
  894. XMPID frameGroupID,
  895. XMPBoolean isOverlaid)
  896. void RemoveEmbeddedFrame(XMPFrame* frame)
  897. void ChangePresentation(
  898. XMPFrame* frame,
  899. XMPName* viewType)
  900. XMPStorageUnit* GetContainingPartProperties(
  901. XMPFrame* displayFrame)
  902. void ContainingPartPropertiesChanged(
  903. XMPFrame* displayFrame,
  904. XMPStorageUnit* propertyUnit)
  905. XMPPtr ReadActionState(
  906. XMPStorageUnitView* storageUnitView)
  907. void WriteActionState(
  908. XMPPtr actionState, 
  909. XMPStorageUnitView* storageUnitView)
  910. void DisposeActionState(
  911. XMPActionData actionState, 
  912. XMPDoneState doneState)
  913. XMPPtr ReadPartInfo(
  914. XMPStorageUnitView* storageUnitView)
  915. void WritePartInfo(
  916. XMPPtr partInfo, 
  917. XMPStorageUnitView* storageUnitView)
  918. XMPPart(
  919. XMPStorageUnit* storageUnit, 
  920. XMPSession* session);
  921. ~XMPPart()
  922. XMPID GetID()
  923. XMPStorageUnit* GetStorageUnit()
  924. XMPSize Purge(XMPSize size)
  925. XMPBoolean HasExtension(
  926. XMPType extensionName);
  927. XMPExtension* GetExtension(
  928. XMPType eid  ReleaseExtension(
  929. XMPExtension* extension);sion* extension);
  930. void MouseEnterFrame(XMPFrame* frame, XMPPoint where)
  931. void MouseLeaveFrame(XMPFrame* frame, XMPPoint where)
  932. XMPExtension
  933. XMPObject* GetBase();
  934. void Release()
  935. Basic part environment
  936. These are the basic calls which could be of interest to the part developer. This initial section represents those calls the developer of a simple part handler would wish to use. Some viewers, which have no editing behavior and do not allow changes to thei
  937. r contents, could use a much smaller subset of this API.
  938. XMPArbitrator
  939. XMPBoolean RequestFocusSet(
  940. XMPFocusSet* focusSet,
  941. XMPFrame* requestingFrame);
  942. void RelinquishFocusSet(
  943. XMPFocusSet* focusSet,
  944. XMPFrame* relinquishingFrame);
  945. XMPCanvas
  946. XMPCanvas(
  947. XMPGraphicsSystem graphicsSystem,  XMPPlatformCanvas platformCanvas, 
  948. XMPBoolean  isDynamic, 
  949. XMPBoolean  isOffscreen);
  950. ~XMPCanvas();
  951. XMPGraphicsSystem GetGraphicsSystem();
  952. XMPPlatformCanvas GetPlatformCanvas();
  953. XMPBoolean IsDynamic();
  954. XMPBoolean IsOffscreen();
  955. XMPClipboard
  956. void Clear();
  957. XMPStorageUnit* GetStorageUnit();
  958. XMPDispatcher
  959. void SetMouseRegion(XMPRgnHandle area);
  960. XMPRgnHandle GetMouseRegion();
  961. void RegisterIdleFrame(
  962. XMPFrame* frame,
  963. XMPIdleFrequency frequency);
  964. void UnregisterIdleFrame(XMPFrame* frame);
  965. XMPDraft
  966. XMPDraftID GetID();
  967. XMPDraftName GetName();
  968. void SetName(XMPDraftName name);
  969. void Release();
  970. XMPStorageUnit* CreateStorageUnit();
  971. XMPStorageUnit* GetStorageUnit(
  972. XMPStorageUnitID id);
  973. void RemoveStorageUnit(
  974. XMPStorageUnit* storageUnit);
  975. void RemoveFromDocument();
  976. XMPBoolean ChangedFromPrev(); 
  977. XMPFrame* CreateFrame(
  978. XMPFrame* containingFrame,
  979. XMPShape*  frameShape,
  980. XMPPart*  part,
  981. XMPUShort  frameGroup,
  982. XMPBoolean  isOverlaid);
  983. XMPFrame* GetFrame(XMPStorageUnitID id);
  984. void RemoveFrame(XMPFrame* frame);
  985. XMPPart* CreatePart(XMPType partType);
  986. XMPPart* GetPart(XMPStorageUnitID id);
  987. void RemovePart(XMPPart* part);
  988. XMPLink* CreateLink();
  989. XMPLink* GetLink(
  990. XMPStorageUnitID id,
  991. XMPLinkSpec* theLinkSpec);
  992. void RemoveLink(XMPLink* link);
  993. XMPWindow* CreateWindow(
  994. XMndow,
  995. XMPFrame* sourceFrame);PFrame* sourceFrame);
  996. XMPWindow* GetWindow(XMPStorageUnitID id);
  997. XMPLayout* CreateLayout(
  998. XMPFrame* containingFrame,
  999. XMPShape* frameShape,
  1000. XMPPart* part,
  1001. XMPUShort frameGroup,  
  1002. XMPLayout* GetLayout(XMPStorageUnitID id);
  1003. void  RemoveLayout(XMPLayout* layout);
  1004. XMPDraftPermissions GetPermissions();
  1005. XMPDragAndDrop
  1006. void Clear();
  1007. XMPStorageUnit* GetStorageUnit();
  1008. XMPDropResult StartDrag(
  1009. XMPFrame* srcFrame,
  1010. XMPValueType imageType,
  1011. XMPPtr image,
  1012. XMPPart** destPart,
  1013. XMPPtr refCon);
  1014. XMPFocusSet
  1015. XMPFocusSet();
  1016. ~XMPFocusSet();
  1017. void Add(XMPTypeToken focus);
  1018. XMPFrame
  1019. XMPFrame*    GetContainingFrame();
  1020. void SetContainingFrame(XMPFrame* frame);
  1021. XMPLayout* GetLayout();
  1022. void    SetLayout(XMPLayout* layout);
  1023. XMPWindow* GetWindow();
  1024. XMPCanvas* GetCanvas();
  1025. XMPULong GetFrameGroup();
  1026. void    SetFrameGroup(XMPULong groupID);
  1027. XMPPtr GetAttributeBundle();
  1028. void SetAttributeBundle(
  1029. XMPPtr attributeBundle);
  1030. XMPBoolean IsOverlaid();
  1031. void    SetOverlaid(XMPBoolean isOverlaid);
  1032. XMPBoolean IsFrozen();
  1033. void    SetFrozen(XMPBoolean isFrozen);
  1034. XMPBoolean UsesCachedImage();
  1035. void    SetUsesCachedImage(
  1036. XMPBoolean usesCachedImage);
  1037. XMPBoolean DoesPropagateEvents();
  1038. void    SetPropagateEvents(
  1039. XMPBoolean doesPropagateEvents);
  1040. XMPPart* GetPart();
  1041. void ChangePart(XMPPart* part);
  1042. XMPInfoType GetPartInfo();
  1043. void    SetPartInfo(XMPInfoType partInfo);
  1044. XMPShape* GetFrameShape();
  1045. void ChangeFrameShape(XMPShape* shape);
  1046. XMPShape* RequestFrameShape(XMPShape* shape);
  1047. XMPShape* GetClipShape();
  1048. void ResetClipShape();
  1049. void IntersectClipShape(XMPShape* sectShape);
  1050. void SubtractClipShape(XMPShape* diffShape);
  1051. XMPShape* GetAggregateClipShape();
  1052. XMPShape* GetUsedShape();
  1053. void ChangeUsedShape(XMPShape* shape);
  1054. XMPShape* GetActiveShape();
  1055. void ChangeActiveShape(XMPShape* shape);
  1056. XMPTransform* GetExternalTransform();
  1057. XMPTransform* GetInternalTransform();
  1058. void ChangeExternalTransform(
  1059. XMPTransform* transform);
  1060. void ChangeInternalTransform(
  1061. XMPTransform* transform);
  1062. XMPTransform* GetAggregateExternalTransform();
  1063. XMPTransform* GetAggregateInternalTransform();
  1064. XMPBoolean IsDroppable();
  1065. void    SetDroppable(XMPBoolean isDroppable);
  1066. XMPBoolean IsDragging();
  1067. void    SetDragging(XMPBoolean isDragging);
  1068. void Invalidate(XMPShape* invalidShape);
  1069. void InvalidateAggregateTransform();
  1070. void Draw(XMPShape* invalidShape);
  1071. XMPHighlight GetHighlight();
  1072. void ChangeHighlight(XMPHighlight highlight);
  1073. void Release();                    
  1074. XMPLayout
  1075. XMPCanvas* GetCanvas();
  1076. void SetCanvas(XMPCanvas* canvas);
  1077. XMPWindow* GetWindow();
  1078. void SetWindow(XMPWindow* window);
  1079. void AddFrame(
  1080. XMPFrame* frame,
  1081. XMPFrame* siblinmePosition position);ion position);
  1082. void RemoveFrame(XMPFrame* frame);
  1083. void Internalize();
  1084. void Externalize();
  1085. XMPLink 
  1086. XMPStorageUnit* GetStorageUnit();
  1087. XMPID GetID();
  1088. void ContentChanged();
  1089. void RegisterDependent(XMPPart* clientPart);
  1090. void UnregisterDependent(XMPPart* clientPart);
  1091. void Externalize();
  1092. XMPMenuBar 
  1093. void AddMenuBefore(
  1094. XMPMenuID menuID,
  1095. XMPPlatformMenu menu,
  1096. XMPPart* part,
  1097. XMPMenuID beforeID);
  1098. void AddMenuLast(
  1099. XMPMenuID menuID,
  1100. XMPPlatformMenu menu,
  1101. XMPPart* part);
  1102. void Display();
  1103. void RegisterCommand(
  1104. XMPCommandID command,
  1105. XMPMenuID menu,
  1106. XMPMenuItemID menuItem);
  1107. XMPBoolean IsCommandRegistered(
  1108. XMPCommandID command);
  1109. XMPBoolean IsCommandSynthetic(
  1110. XMPCommandID command);
  1111. XMPNameSpace
  1112. XMPISOStr GetName();
  1113. void Register(XMPISOStr key, XMPPtr value);
  1114. void Register(XMPOSType key, XMPPtr value);
  1115. void Register(XMPSLong key, XMPPtr value);
  1116. void Unregister(XMPISOStr key);
  1117. void Unregister(XMPOSType key);
  1118. void Unregister(XMPSLong key);
  1119. XMPPtr GetValue(XMPISOStr key);
  1120. XMPPtr GetValue(XMPOSType key);
  1121. XMPPtr GetValue(XMPSLong key);
  1122. XMPValueIterator* CreateValueIterator();
  1123. XMPShape
  1124. XMPShape(
  1125. XMPGraphicsSystem graphicsSystem,
  1126. XMPPlatformShape platformShape);
  1127. ~XMPShape();
  1128. XMPGraphicsSystem GetGraphicsSystem();
  1129. XMPPlatformShape GetPlatformShape();
  1130. void SetPlatformShape(
  1131. XMPGraphicsSystem graphicsSystem,  XMPPlatformShape platformShape);
  1132. void CopyFrom(XMPShape* sourceShape);
  1133. XMPBoolean IsSameAs(XMPShape* compareShape);
  1134. void Subtract(XMPShape* diffShape);
  1135. void Intersect(XMPShape* sectShape);
  1136. XMPBoolean ContainsPoint(XMPPoint point);
  1137. void Transform(XMPTransform* transform);
  1138. XMPStorageSystem
  1139. XMPContainer* CreateContainer(
  1140. XMPContainerType containerType,
  1141. XMPContainerID id);
  1142. XMPContainer* GetContainer(
  1143. XMPContainerType containerType,
  1144. XMPContainerID id);
  1145. void NeedSpace(
  1146. XMPSize memSize,
  1147. XMPBoolean doPurge);
  1148. XMPStorageUnit
  1149. XMPDraft* GetDraft();
  1150. void Release();
  1151. XMPStorageUnit* Focus(
  1152. XMPPropertyName propertyName,
  1153. XMPPositionCode propertyPosCode,
  1154. XMPValueType valueType,
  1155. XMPValueIndex valueIndex,
  1156. XMPPositionCode valuePosCodeName(); orageUnit* Externalize(); 
  1157. XMPStorageUnit* Internalize(); 
  1158. XMPID  GetID(); 
  1159. XMPStorageUnitName GetName(); 
  1160. void SetName(XMPStorageUnitName name);
  1161. XMPStorageUnit* AddProperty(
  1162. XMPPropertyName propertyName);
  1163. XMPStorageUnit* AddValue(XMPValueType type);
  1164. XMPStorageUnit* Remove();
  1165. void  CopyFrom(XMPStorageUnit* fromSU);
  1166. XMPValueType GetType();
  1167. void  SetType(XMPValueType valueType);
  1168. XMPULong  GetValue(
  1169. XMPULong length,
  1170. XMPValue value);
  1171. void  SetValue(
  1172. XMPULong length,
  1173. XMPValue value);
  1174. void  InsertValue(
  1175. XXMPValue value);XMPValue value);
  1176. void  DeleteValue(XMPULong length);
  1177. XMPStorageUnitCursor
  1178. XMPStorageUnitCursor(
  1179. XMPPropertyID propertyID,
  1180. XMPValueType valueType,
  1181. XMPValueIndex valueIndex);
  1182. XMPStorageUnitCursor(
  1183. XMPStorageUnitCursor old,
  1184. XMPStorageUnit* su,
  1185. XMPPositionCode propertyPosCode,
  1186. XMPPositionCode valuePosCode);
  1187. ~XMPStorageUnitCursor();
  1188. XMPStorageUnitView
  1189. XMPStorageUnitView* Externalize(); 
  1190. XMPStorageUnitView* Internalize(); 
  1191. XMPStorageUnit* GetStorageUnit(); 
  1192. XMPStorageUnitName GetName(); 
  1193. void SetName(XMPStorageUnitName name);
  1194. XMPStorageUnitView* AddProperty(
  1195. XMPPropertyName propertyName);
  1196. XMPStorageUnitView* AddValue(
  1197. XMPValueType type);
  1198. XMPStorageUnitView* Remove();
  1199. void CopyFrom(XMPStorageUnit* fromSU);
  1200. XMPValueType GetType();
  1201. void SetType(XMPValueType valueType);
  1202. XMPULong  GetValue(
  1203. XMPULong length,
  1204. XMPValue value);
  1205. void  SetValue(
  1206. XMPULong length,
  1207. XMPValue value);
  1208. void  InsertValue(
  1209. XMPULong length,
  1210. XMPValue value);
  1211. void  DeleteValue(XMPULong length);
  1212. XMPSymbols 
  1213. XMPNameSpace* CreateNameSpace(
  1214. XpeSpec contentType,
  1215. XMPNameSpace* inheritsFrom,
  1216. XMPULong  numExpectedEntries);PULong  numExpectedEntries);
  1217. void DeleteNameSpace(
  1218. XMPNameSpace* theNameSpace);
  1219. XMPNameSpace*  HasNameSpace(
  1220. XMPISOStr spaceName);
  1221. XMPSession
  1222. void Close();
  1223. XMPWindowState* GetWindowState();
  1224. XMPDispatcher* GetDispatcher();
  1225. XMPArbitrator* GetArbitrator();
  1226. XMPStorageSystem*  GetStorageSystem();
  1227. XMPClipboard* GetClipboard();
  1228. XMPDragAndDrop* GetDragAndDrop();
  1229. XMPSymbols* GetSymbols();
  1230. XMPMessageInterface* GetMessageInterface(); 
  1231. XMPNameResolver* GetNameResolver(); 
  1232. XMPTranslation* GetTranslation(); 
  1233. XMPUndo* GetUndo();
  1234. XMPTypeToken Tokenize(XMPType type);
  1235. void RemoveEntry(XMPType type);
  1236. XMPType GetType(XMPTypeToken token);
  1237. XMPSemanticInterface* GetShellSemtInterface();
  1238. XMPSemanticInterface* GetSemanticInterface();
  1239. XMPTransform
  1240. XMPTransform(
  1241. XMPGraphicsSystem graphicsSystem,  XMPPlatformTransform platformTransform);
  1242. ~XMPTransform();
  1243. XMPGraphicsSystem GetGraphicsSystem();
  1244. XMPPlatformTransform GetPlatformTransform();
  1245. void SetPlatformTransform(
  1246. XMPGraphicsSystem graphicsSystem,  XMPPlatformTransform platformTransform);
  1247. XMPTransform* Reset();
  1248. XMPTransform* CopyFrom(
  1249. XMPTransform* sourceTransform);
  1250. XMPTransform* Invert();
  1251. XMPBoolean IsSameAs(
  1252. XMPTransform* compareTransform);
  1253. XMPTransform* PreCompose(
  1254. XMPTransform* transform);
  1255. XMPTransform* PostCompose(
  1256. XMPTransform* transform);
  1257. XMPPoint TransformPoint(XMPPoint point);
  1258. XMPTranslation
  1259. XMPBoolean GetTranslateMethod(
  1260. XMPTypeSet* givenTypes,
  1261. XMPOSType nativeType,
  1262. XMPTranslateResult* result,
  1263. XMPTranslte(
  1264. XMPStorageUnitView* storageUnit,  XMPTranslateMethod howToTranslate);Type);
  1265. XMPPtr Translate(
  1266. XMPStorageUnitView* storageUnit,  XMPTranslateMethod howToTranslate);
  1267. XMPPtr Translate(
  1268. XMPPtr fromData,
  1269. XMPOSType givenType,
  1270. XMPTranslateMethod howToTranslate);
  1271. XMPTypeSet
  1272. XMPTypeSet();
  1273. ~XMPTypeSet();
  1274. void AddType(XMPOSType type);
  1275. void RemoveType(XMPOSType type);
  1276. XMPBoolean ContainsType(XMPOSType type);
  1277. XMPULong GetTypeCount();
  1278. XMPUndo
  1279. void AddActionToHistory(
  1280. XMPPart* whichPart,
  1281. XMPActionData actionData,
  1282. XMPAo();nType actionType,
  1283. XMPName actionLabel);
  1284. void Undo();
  1285. void Redo();
  1286. void MarkActionHistory();
  1287. void ClearActionHistory(
  1288. XMPRespectMarksChoices respectMarks);
  1289. void ClearRedoHistory();
  1290. void PeekUndoHistory(
  1291. XMPPart** part,
  1292. XMPActionData* actionData,
  1293. XMPActionType* actionType,
  1294. XMPName* actionLabel);
  1295. void PeekRedoHistory(
  1296. XMPPart** part,
  1297. XMPActionData* actionData,
  1298. XMPActionType* actionType,
  1299. XMPName* actionLabel);
  1300. XMPWindow
  1301. XMPPlatformWindow GetPlatformWindow();
  1302. XMPFrame* GetSourceFrame();
  1303. XMPCanvas* GetCanvas();
  1304. void SetCanvas(XMPCanvas* canvas);
  1305. XMPFrame* GetRootFrame();
  1306. void AddFrame(
  1307. XMPFrame* newFrame,
  1308. XMPFrame* siblingFrame,
  1309. XMPFramePosition position);
  1310. void RemoveFrame(XMPFrame* oldFrame);
  1311. XMPFrame* GetFrameUnderPoint(XMPPoint aPoint);
  1312. void Close();
  1313. void Open();
  1314. void Internalize();
  1315. void Externalize();
  1316. XMPBoolean IsActive();
  1317. XMPWindowState
  1318. XMPWindow* GetXMPWindow(
  1319. XMPPlatformWindow aWindow);
  1320. XMPWindow* GetActiveWindow();
  1321. XMPMenuBar GetBaseMenuBar();
  1322. void UpdateBaseMenus();
  1323. void SetMenuUpdateProc(
  1324. XMPMenuUpdaroc);cPtr proc);
  1325. XMPMenuBar* GetCurrentMenuBar();
  1326. XMPMenuBar* CopyBaseMenuBar();
  1327. Scripting & semantic event processing
  1328. XMPSemanticInterface 
  1329. void InstallObjectAccessor(
  1330. DescType desiredClass,
  1331. DescType containerType,
  1332. XMPAccessorProcPtr theAccessor,
  1333. XMPSLong accessorRefcon);
  1334. void GetObjectAccessor(
  1335. DescType desiredClass,
  1336. DescType containerType,
  1337. XMPAccessorProcPtr* theAccessor,
  1338. XMPSLong* accessorRefcon);
  1339. void  CallObjectAccessor(
  1340. XMPPart*  thePart,
  1341. DescType  desiredClass,
  1342. XMPOSLToken* containerToken,
  1343. DescType ctAccessor(
  1344. DescType desiredClass,
  1345. DescType containerType,
  1346. XMPAccessorProcPtr theAccessor);cessor(
  1347. DescType desiredClass,
  1348. DescType containerType,
  1349. XMPAccessorProcPtr theAccessor);
  1350. void SetObjectCallbacks(
  1351. XMPCompareProcPtr compareProc,
  1352. XMPCountProcPtr countProc,
  1353. XMPDisposeTokenProcPtr disposeTokenProc,
  1354. XMPGetMarkTokenProcPtr getMarkTokenProc,
  1355. XMPMarkProcPtr markProc,
  1356. XMPAdjustMarksProcPtr adjustMarksProc,
  1357. XMPPtr reserved);
  1358. void InstallEventHandler(
  1359. AEEventClass theAEEventClass,
  1360. AEEventID theAEEventID,
  1361. XMPEveer(
  1362. AEEventClass theAEEventClass,
  1363. AEEventID theAEEventID,
  1364. XMPEventHandlerProcPtr handler);heAEEventClass,
  1365. AEEventID theAEEventID,
  1366. XMPEventHandlerProcPtr handler);
  1367. void GetEventHandler(
  1368. AEEventClass theAEEventClass,
  1369. AEEventID theAEEventID,
  1370. XMPEventHandlerProcPtr* handler,
  1371. XMPSLong* handlerRefcon);
  1372. void InstallCoercionHandler(
  1373. DescType fromType,
  1374. DescType toType,
  1375. XMPCoercionHandler handler,
  1376. XMPSLong handlerRefcon,
  1377. XMPBoolean fromTypeIsDesc);
  1378. void RemoveCoercionHandler(
  1379. DescType fromType,
  1380. DescType toType,
  1381. XMPCo fromType,
  1382. DescType toType,
  1383. XMPCoercionHandler* handler,
  1384. XMPSLong* handlerRefcon,
  1385. XMPBoolean* fromTypeIsDesc);er,
  1386. XMPSLong* handlerRefcon,
  1387. XMPBoolean* fromTypeIsDesc);
  1388. void RemoveSpecialHandler(
  1389. AEKeyword functionClass,
  1390. XMPEventHandlerProcPtr handler);
  1391. void GetSpecialHandler(
  1392. AEKeyword functionClass,
  1393. XMPEventHandlerProcPtr* handler);
  1394. XMPMessageInterface
  1395. XMPSShort  CreateEvent(
  1396. AEEventClass theAEEventClass,
  1397. AEEventID  theAEEventID,
  1398. AEAddressDesc* target,
  1399. XMPSLong  transactionID,
  1400. AppleEvent*  result);
  1401. void  Send(
  1402. XMPPart*  thePart,
  1403. AppleEvent*  theAppleEvent,
  1404. AppleEvent*  reply,
  1405. AESendMode  sendMode,
  1406. AESendPriority  sendPriority,
  1407. XMPULong  timeOutInTicks,
  1408. XMPIdleProcPtr  idleProc,
  1409. XMPEventFilterProcPtr filterProc);
  1410. XMPBoolean ProcessSemanticEvent(
  1411. const XMPEventData theEvent);
  1412. XMPNameResolver
  1413. XMPPart* Resolve(
  1414. AEDesc*  theObject,
  1415. XMPSShort  callbackFlags,
  1416. XMPOSLToken* token);
  1417. XMPOSLToken* CreatePartToken(XMPPart* aPart);
  1418. XMPOSLToken* CreateToken(
  1419. DescType  type,
  1420. XMPPart*  inPart,
  1421. XMPPtr  data);
  1422. void  DisposeToken(XMPOSLToken* theToken);
  1423. Extended event dispatch control
  1424. These calls are available to the part developer, but generally uninteresting unless some form of advanced event dispatching is required. In this case, the part developer has to implement XMPFocusModule and/or XMPDispatchModule objects and install them  in
  1425.  the arbitrator and dispatcher respectively.
  1426. XMPArbitrator
  1427. void RegisterFocus(
  1428. XMPTypeToken focus,
  1429. XMPFocusModule* focusModule);
  1430. void UnregisterFocus(XMPTypeToken focus);
  1431. XMPFocusModule
  1432. XMPBoolean IsFocusExclusive(
  1433. XMPTypeToken focus)
  1434. void SetFocusOwnership(
  1435. XMPTypeToken focus,
  1436. XMPFrame* frame)
  1437. void UnsetFocusOwnership(
  1438. XMPTypeToken focus,
  1439. XMPFrame* frame)
  1440. XMPFrame* GetFocusOwner(XMPTypeToken focus)
  1441. XMPFocusOwnerIterator* CreateOwnerIterator(XMPTypeToken focus)
  1442. XMPDispatcher
  1443. void AddDispatchModule(
  1444. XMPDispatchCode code,
  1445. XMPDispatchModule* dispatchModule,
  1446. XMPBoolean monitor);
  1447. void RemoveDispatchModule(XMPDispatchCode code);
  1448. XMPDispatchModule
  1449. XMPDispatchModule(XMPSession* session);
  1450. ~XMPDispatchModule();
  1451. XMPBoolean Dispatch(XMPEventData event);
  1452. Extended draft control
  1453. These calls are available to the part developer, but generally uninteresting unless some form of special control over drafts is desired.
  1454. XMPDocument
  1455. XMPDocument* CollapseDrafts(
  1456. XMPDraft* from,
  1457. XMPDraft* to);
  1458. XMPDraft* GetDraft(
  1459. XMPDraftPermissions perms,
  1460. XMPDraftID id,
  1461. XMPDraft* draft,
  1462. XMPPositionCode posCode,
  1463. XMPBoolean release);
  1464. XMPDraft* GetBaseDraft(
  1465. XMPDraftPermissions perms); 
  1466. XMPDraft* CreateDraft(
  1467. XMPDraft* below,
  1468. XMPBoolean releaseBe ReleaseDraft(XMPDraft* draft);(XMPDraft* draft);
  1469. void SaveToAPrevDraft(
  1470. XMPDraft* from,
  1471. XMPDraft* to);
  1472. XMPDraft* SetBaseDraftFromForeignDraft(
  1473. XMPDraft* draft);
  1474. Container application implementors
  1475. These APIs are primarily interesting to the developer of a shell application or those retrofitting existing applications to contain OpenDoc parts.
  1476. XMPContainer
  1477. XMPStorageSystem* GetStorageSystem()
  1478. XMPContainerID GetID();
  1479. XMPContainerName GetName()
  1480. void SetName(XMPContainerName name)
  1481. void Release()
  1482. XMPDocument* GetDocument(XMPDocumentID id); 
  1483. XMPDocument
  1484. XMPContainer* GetContainer();
  1485. XMPDocumentID GetID();
  1486. XMPDocumentName GetName();
  1487. void SetName(XMPDocumentName name);
  1488. void Release();
  1489.  
  1490.  
  1491.