\begindata{text,539047252} \textdsversion{12} \template{be2guide} \define{global

\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 and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation, and that the name of IBM not be used in advertising or
publicity pertaining to distribution of the software without specific,
written prior permission.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ANY 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}