\begindata{text,539047252} \textdsversion{12} \template{be2guide} \define{global } \define{underline menu:[Font~1,Underline~41] attr:[Flags Underline Int Set]} \define{index menu:[Title,Index~91] attr:[FontFace Italic Int Set]} \define{indexi menu:[Title,InvisibleIndex~92] attr:[Script PreviousScriptMovement Point -2] attr:[Flags Hidden Int Set] attr:[FontFace Italic Int Set]} \define{itemize } \define{fixedtext menu:[Region~4,Fixedtext] attr:[Justification LeftJustified Point 0] attr:[FontFace FixedFace Int Set] attr:[FontFamily AndyType Int 0] attr:[FontSize ConstantFontSize Point 10]} \define{fixedindent menu:[Region~4,Fixedindent] attr:[LeftMargin LeftMargin Cm 83230] attr:[Justification LeftJustified Point 0] attr:[FontFace FixedFace Int Set] attr:[FontFamily AndyType Int 0] attr:[FontSize ConstantFontSize Point 10]} \define{paramname menu:[Font~1,Paramname] attr:[FontFace Italic Int Set]} \formatnote{\chapter{Data Object}} \indexi{Data object} The class \italic{dataobject} provides the data and methods needed to maintain, store, and manipulate information. The information in a data object is displayed through views onto that data object, and any one data object may have more than one view onto it at any given time. If the data object is changed, then all the views are updated automatically. Data objects are necessary in two cases: first, if you want to be able to write data to a file, and second, if you want to have several different views on a single piece of data, for example, if you want both a table and a graph to display the same data. \section{Quick reference list for Dataobject} \fixedtext{\bold{dataobject_}GetID }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{long \bold{dataobject_}GetModified }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{\bold{dataobject_}GetWriteID }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{short \bold{dataobject_}Get }\fixedindent{(struct dataobject *\paramname{dataobject}, struct atom *\paramname{property}, struct atom **\paramname{type}, long *\paramname{rock});} \fixedtext{int \bold{dataobject_}ListCurrentViews }\fixedindent{(struct dataobject *\paramname{dataobject}, struct view **\paramname{array}, int \paramname{size});} \fixedtext{void \bold{dataobject_}Put }\fixedindent{(struct dataobject *\paramname{dataobject}, struct atom *\paramname{property}, struct atom *\paramname{type}, long \paramname{rock});} \fixedtext{long \bold{dataobject_}Read }\fixedindent{(struct dataobject *\paramname{dataobject}, FILE *\paramname{file}, long \paramname{id});} \fixedtext{void \bold{dataobject_}RestoreModified }\fixedindent{(struct dataobject *\paramname{dataobject}, long \paramname{oldmodified});} \fixedtext{void \bold{dataobject_}SetAttributes }\fixedindent{(struct dataobject *\paramname{dataobject}, struct attributes *\paramname{attributes});} \fixedtext{\bold{dataobject_}SetID }\fixedindent{(struct dataobject *\paramname{dataobject}, long \paramname{newValue});} \fixedtext{void \bold{dataobject_}SetModified }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{\bold{dataobject_}SetWriteID }\fixedindent{(struct dataobject *\paramname{dataobject}, long \paramname{newValue});} \fixedtext{\bold{dataobject_}UniqueID }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{char *\bold{dataobject_}ViewName }\fixedindent{(struct dataobject *\paramname{dataobject});} \fixedtext{long \bold{dataobject_}Write }\fixedindent{(struct dataobject *\paramname{dataobject}, FILE *\paramname{file}, long \paramname{writeid}, int \paramname{level});} \section{Overview of data objects} Data objects are used to represent permanent storage in the Andrew Toolkit. They can be read or written to files, and also provide private operations that make sense only for a particular set of data objects. Views usually represent views onto data objects; in other words, when a view is created, it is usually associated with a particular data object. In normal use, data objects are used to represent the graphical or textual entities one edits. These entities are usually stored in files for permanent storage, although other uses of data objects include, for example, the message line in an editor window, which is not a permanent object. In order to display or edit a data object, we have a view "look" onto the data object. A data object's view provides methods for displaying the data, methods for posting menus, methods for handling keyboard and mouse input, and other miscellaneous methods. See the section \bold{View }for more information on view methods and procedures. \subsection{Creating data objects} \indexi{Data object++Creating} \paragraph{Creating a new data object} \indexi{ \italic{dataobject_New}} \example{struct *dataobject_New ( ) } \leftindent{ \bold{Class procedure description.} instance of a new data object. \bold{Return value.} \italic{dataobject_New} creates an A pointer to the new data object. \bold{Usage.} You should never need to call this procedure directly. Instead, you should create new data objects by creating subclasses of the class \italic{dataobject}. \bold{Example.} If \italic{text} is a \italic{dataobject}, then the following creates an instance of \italic{text}: \example{ struct text *t; t= text_New (); } } \subsection{Referencing data objects from a view} \indexi{Data object++Referencing view} If you are working with a \italic{view/dataobject} pair, or inset, your \italic{view} class method definitions will need to access its \italic{dataobject}. In general, if the view you are dealing with is a \italic{struct view *}, and not a \italic{view} subclass, you would write the following: \programexample{ struct view *v; struct dataobject *do; do = v->dataobject; } However, if the view you are dealing with is a subclass of the class \italic{view}, such as \italic{textview} and its corresponding \italic{dataobject} \italic{text}, you would write the following: \programexample{ struct textview *txtview; struct text *txt; txt = (struct text *) txtview->header.view.dataobject; } If you are defining your own \italic{view/dataobject} pair, you will want to access the \italic{dataobject} from the \italic{FullUpdate}, \italic{Update}, and \italic{Hit} methods, the scroll bar routines, and any other method you may write which requires communication with the data object. \subsection{Data stream} \indexi{Data stream} \indexi{Data object++Data stream} The data stream is the external representation of a data object, and is used when the data object must be communicated to another program, either through a file for that program to read or through a pipe (e.g., a pipe to the window manager as part of a cutting or pasting operation). The data stream is represented as a collection of data object definitions and views that refer to those data objects. Data objects can be included in a file using the construct: \example{\\begindata(datatype, dataID) <data object data> \\enddata(datatype, dataID)} The \italic{\\begindata, \\enddata} pair mark the extent of the data included in a particular data object. The \italic{datatype} is the type of data being stored (e.g. text, raster, etc). The \italic{dataID} is a unique ID number that identifies the particular data object. No two data objects in the same file/paste stream will have the same \italic{dataID}; however, two data objects in different streams may coincidentally have the same ID number. Note that there are newlines after the \italic{\\begindata} statement, after the data object dependent data, and after the \italic{\\enddata} statement. These newlines are necessary for data object parsing. \paragraph{Characteristics of data streams} Data streams representation meets the following criteria: \itemize{ Handle an arbitrary collection of views and data objects. Share data objects between two views in the same document. Specify a view (identified by name) so that commands can be sent to it. Contain only printable ascii characters. Possess a simple parsing algorithm. Recognize datastream and non-datastream formats and treat them accordingly. } \paragraph{Reserved characters for data streams} \\ \{ \} For datastream files, the characters \\, \{, and \} are special. If these characters are to appear in the datastream they must be quoted. Thus \\\\, \\ \{, and \\ \} produce literal occurrences of \\, \{, and \}, respectively. In non-datastream files, no special significance is attached to the reserved characters, and literal occurrences of it should not be preceded by an extra \\. \begindata{bp,538271496} \enddata{bp,538271496} \view{bpv,538271496,1312,0,0} \subsection{Reading data objects} \indexi{Data object++Read} The \italic{Read} method for a data object should read its external representation from a file that conforms to the datastream format. Some data objects may try to read non-datastream formats. For example, the \italic{text} object reads a normal text file and the \italic{raster} object reads a graphics file. Otherwise the stream is assumed to be one written by the object's \italic{Write} routine, with the file pointer right after the \\begindata\{...\}. No version checking is done, although a particular object may implement its own. \paragraph{Reading a data object } \indexi{Data object++Reading} \indexi{ \italic{dataobject_Read}} \example{void dataobject_Read(do, file, id) struct dataobject *do; FILE *file; long id: } \leftindent{ \bold{Method description.} \italic{dataobject_Read} takes a \italic{stdio} \italic{file} and reads the external representation of the data object from the file into the data structures provided in \italic{do}. The third parameter, \italic{id}, is either zero, indicating that no data stream header was found, or an integer identification for the data object, guaranteed to be unique within the data stream. The class' specific \italic{dataobject_Read} method is responsible for setting \italic{do}'s ID field, using the \italic{dataobject_SetID} macro. \bold{Return value.} Most \italic{dataobject_Read} methods return status codes indicating success or failure (e.g., premature end of file (EOF), etc.). \bold{Side effects.} \italic{dataobject_Read} modifies \italic{do}'s data structures. For example, a text object would be modified to contain the text in a file. \bold{Usage.} A class' \italic{dataobject_Read} method is sometimes invoked by another specialization of \italic{dataobject_Read} when it encounters a \italic{\\begindata} within its external representation. When a \italic{Read} method encounters data for a class \italic{x}, it should create an instance of the class (using \italic{x_New}), enter it in the data dictionary (using \italic{dictionary_Insert}), and finally read in the external representation, by calling \italic{x_Read}. See Example 11, Vol. I for more detail on \italic{Read}. } \begindata{bp,538271624} \enddata{bp,538271624} \view{bpv,538271624,1313,0,0} \subsection{Writing data objects} \indexi{Data object++Writing} The \italic{Write} method for a \italic{dataobject} must write the contents of the \italic{dataobject} to a given \italic{stdio} stream. Because the Toolkit architecture supports embedded data objects and multiple views of the same data object, there is a mechanism to insure that a data object does not write itself more than once. The mechanism is a \italic{writeID}. The first \italic{Write} method generates a \italic{WriteID}. If the method encounters an embedded data object which needs to write itself, it is passed the \italic{WriteID} that the toplevel object generated. The embedded object compares the \italic{writeID} it is passed to the previous \italic{writeID} that it has stored and only writes itself if they are different. The Toolkit also supports a non-datastream representation (e.g., the class \italic{text} has both a datastream and non-datastream representation. See Example 14, Vol. I). There is a mechanism, a \italic{level} parameter, that allows objects to communicate about whether they may write their non-datastream representation. The \italic{level} parameter indicates whether or not a data object is the toplevel data object being written (i.e., not a data object embedded within another data object). If the data object is the toplevel data object, the \italic{level} parameter should be zero. Only toplevel data objects may write a non-datastream representation. A data object that is writing out an embedded data object should call the embedded data object's \italic{Write} method with a non-zero level parameter. If a data object is not the toplevel data object, it \italic{must} write itself out in datastream format, as it cannot make any assumptions about whether the data objects writing it out can handle the other format. \paragraph{Writing a data object} \indexi{Data object++Writing} \indexi{ \italic{dataobject_Write}} \example{long dataobject_Write(do, file, writeID, level) struct dataobject *do; FILE *file; long writeID; int level;} \leftindent{ \bold{Method description.} The \italic{dataobject_Write} method writes the external representation of \italic{do} to \italic{file}. The \italic{writeID} parameter identifies the write operation; the method should just return if it has already written itself out once for this particular write operation. The \italic{level} parameter keeps track of the data object hierarchy: If \italic{dataobject_Write} is being called from another \italic{dataobject_Write} invocation, the\italic{level} parameter should be one more than the caller's level parameter. \bold{Return value.} The Write method should return its object's \italic{UniqueID}, which is the \italic{UniqueID}, used to distinguish the \italic{dataobject} from other \italic{dataobjects} in the file. See the macromethod \italic{dataobject_UniqueID}. \bold{Side effects.} The file is modified by having the object \italic{do}'s external representation written to it. \bold{Usage.} If a data object based upon another type of data object must write its external representation to a file, you should call \italic{dataobject_Write} on that object. The method is therefore typically invoked from another class' specialization of \italic{dataobject_Write}. When the higher-level data object reaches the point where it must write out the child data object's representation, it simply invokes \italic{dataobject_Write} on the child, passing in a \italic{level} parameter one higher than its own. The \italic{level} parameter enables objects to avoid writing out a \italic{\\begindata} if they are the top-level object in a file. The issuer of the write to the top-level object is responsible for generating a unique \italic{writeID} for the write call. Everyone implementing a \italic{dataobject_Write} method is responsible for recording within the dataobject the \italic{writeID} last written to a file. If \italic{dataobject_Write} is invoked multiple times on the same data object, this can be detected by comparing the last stored ID associated with the data object with the \italic{writeID} parameter. If they are equal, \italic{dataobject_Write} should simply return the same\italic{UniqueID}. \bold{Example.} A typical \italic{dataobject__Write} definition might include the following statements: \programexample{ fprintf(file,"\\\\begindata\{%s,%d\}\\n", class_GetTypeName(self),classname_GetTypeName(self)); dataobject_UniqueID(&self->header.dataobject)); <dataobject specific writing code> fprintf(file,"\\\\enddata\{%s,%d\}\\n", class_GetTypeName(self), dataobject_UniqueID(&self->header.dataobject)); } For a more detailed example, see Example 11, Vol. I. } \begindata{bp,538269640} \enddata{bp,538269640} \view{bpv,538269640,1314,0,0} \subsection{The data object's unique ID} \paragraph{Generating a unique ID for a data object} \indexi{Data object++Unique id} \indexi{ \italic{dataobject_UniqueID}} \example{long dataobject_UniqueID (do) struct dataobject *do;} \leftindent{ \bold{Macro method description.} \italic{dataobject_UniqueID} returns a unique identifier for the data object \italic{do}. The identifier will be unique relative to the file that is being written. \bold{Return value.} A long. \bold{Usage.} You should call this method to generate a unique identifier for a data object to return from the \italic{dataobject_Write} method. Arguments to macro methods should not have side effects. } \paragraph{Setting a data object's unique ID field} \indexi{Data object++Setting id} \indexi{ \italic{dataobject_SetID}} \example{dataobject_SetID(id) long id;} \leftindent{ \bold{Macro method description.} associated with a data object. \bold{Usage.} \italic{SetID} changes the id field Arguments to macro methods should not have side effects. } \paragraph{Getting the value of a data object's unique ID field} \indexi{Data object++Getting id} \indexi{ \italic{dataobject_GetID}} \example{long dataobject_GetID (do) struct dataobject *do;} \leftindent{ \bold{Macro method description.} \italic{do}'s ID field. \bold{Return value.} \italic{GetID} returns the value of The value of the ID field for the data object. \bold{Usage.} You would call this method to discover the unique id associated with a data object. } \begindata{bp,538928456} \enddata{bp,538928456} \view{bpv,538928456,1315,0,0} \subsection{The writeID} \paragraph{Setting the WriteID for a data object} \indexi{Data object++Setting write id} \indexi{ \italic{dataobject_SetWriteID}} \example{dataobject_SetWriteID(do, NewID) struct dataobject *do; long NewID;} \leftindent{ \bold{Macro method description.} \italic{SetWriteID} sets the value of data object \italic{do}'s \italic{writeID} field to \italic{NewID}. \bold{Usage.} See the description of the \italic{dataobject_Write} method above. Arguments to macro methods should not have side effects. } \paragraph{Getting the writeID for a data object} \indexi{Data object++Getting write id} \indexi{ \italic{dataobject_GetWriteID}} \example{long dataobject_GetWriteID(do) struct dataobject *do;} \leftindent{ \bold{Macro method description.} \italic{GetWriteID} returns the \italic{WriteID} field of the dataobject \italic{do}. \bold{Return value.} A long, the contents of the \italic{writeID} field. \bold{Usage.} See the description of the \italic{dataobject_Write} method above. Arguments to macro methods should not have side effects. } \begindata{bp,538928520} \enddata{bp,538928520} \view{bpv,538928520,1316,0,0} \subsection{Modifications} \paragraph{Setting a data object's modified flag} \indexi{Data object++Setting modify flag} \indexi{ \italic{dataobject_SetModified}} \example{void dataobject_SetModified(do) struct dataobject *do; } \leftindent{ \bold{Method description.} Calling \italic{dataobject_SetModifiedValue} increments the number returned by \italic{GetModified} by one. \bold{Side effects.} is incremented by one. The modified number for the specified data object \bold{Usage.} Since data objects can be read and written by other data objects, you need to keep track of modifications made to a data object. You should call this method at least once every time a data object's representation changes. } \paragraph{Finding out if a data object has been modified} \indexi{Data object++Modification} \indexi{ \italic{dataobject_GetModified}} \example{long dataobject_GetModified (do) struct dataobject *do; } \leftindent{ \bold{Method description. } \italic{dataobject_GetModified} returns a number equal to the number of times the data object was modified since it was created. \bold{Usage.} Call this method in order to keep track of modifications to a data object. If two calls to this method return the same value, then the data object has not been modified between the calls. } \subsection{The data object's view} \paragraph{Setting the name of the data object's view} \indexi{Data object++Default view} \indexi{ \italic{dataobject_ViewName}} \example{char *dataobject_ViewName (do) struct dataobject *do; } \leftindent{ \bold{Method description.} \italic{dataobject_ViewName} returns the name of the default view to be used for the data object. \bold{Usage. } This method returns the name of the \italic{view} class that draws the default screen representation of the particular data object. If not provided, the default view for a data object whose class is named \italic{x} is \italic{xview}. You should write your own \italic{ViewName} method if you don't want the default name. } \begindata{bp,538929224} \enddata{bp,538929224} \view{bpv,538929224,1317,0,0} \subsection{Attributes} \indexi{Data object++Attributes} \paragraph{Setting the attributes for a data object \indexi{ \italic{dataobject_SetAttributes}}} \example{void dataobject_SetAttributes(do, attributes) struct dataobject *do; struct attributes *attributes;} \leftindent{ \bold{Method description.} \italic{ dataobject_SetAttributes} changes the attributes associated with \italic{do} to \italic{attributes}. \bold{Side effect.} Changes the internal state of a data object in a class-specific manner. \bold{Usage.} Subclasses of \italic{dataobject} may find it useful to have attributes. For example, two attributes that may be associated with a the \italic{simpletext} data object are "filesize" and "readonly". The first is used by the \italic{dataobject_Read} as a hint for making space allocation more efficient (certain allocation schemes are more efficient if the allocator has some idea of the eventual final size). The second attribute controls whether or not the data object can be changed. This method uses a declaration of a property list-like structure for attribute propagation. \example{struct attributes \{ struct attributes *next; /* Representation is a linked list. */ char *key; /* attribute name. */ union \{ /* Value can either be an integer or a string. */ long integer; char *string; \} value; } } \begindata{bp,537558784} \enddata{bp,537558784} \view{bpv,537558784,1319,0,0} Copyright 1992 Carnegie Mellon University and IBM. All rights reserved. \smaller{\smaller{$Disclaimer: Permission to use, copy, modify, and distribute this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice, this permission notice, and the following disclaimer appear in supporting documentation, and that the names of IBM, Carnegie Mellon University, and other copyright holders, not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. IBM, CARNEGIE MELLON UNIVERSITY, AND THE OTHER COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL IBM, CARNEGIE MELLON UNIVERSITY, OR ANY OTHER COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. $ }}\enddata{text,539047252}