\begindata{text,539494632} \textdsversion{12} \template{default} \define{global

advertisement
\begindata{text,539494632}
\textdsversion{12}
\template{default}
\define{global
}
\define{footnote
attr:[Flags OverBar Int Set]
attr:[FontSize PreviousFontSize Point -2]}
\define{programexample
}
\define{itemize
}
\define{enumerate
}
\formatnote{\chapter{Example 1:
program
}}
Creating a class and an application
This section describes how to create a simple class and how to create an
application program that uses the class. The application program will
create a new window, create an instance of the class, and set the
instance
in the window. Then the instance of the class will draw the string
\italic{hello world} in the window's center. This example program
illustrates the following activities: \
\itemize{\leftindent{declaring a class
defining class procedures and methods
drawing, using the Andrew Toolkit class \italic{Graphic}
compiling in the Andrew Toolkit environment
creating and running a stand-alone application program
}}
After reading Example1, you will know the very basic program structure
needed to create a simple Andrew Toolkit class and a stand-alone
application program that uses an object that is an instance of that
class.
Later examples will introduce the structures you need in order to build
an
object that responds to user input (e.g., mouse, keyboard, menus), reads
and writes to files, and so on. \
The discussion that follows presents a step-by-step description of how to
write the example program. If you were to follow the steps, you would
produce a program, called \italic{helloworldapp}, in five files: \
\itemize{\leftindent{a hwview.H file -- will contain the class definition
for the \italic{helloworldview} class, the class whose instances draw the
string \italic{hello world}. The class \italic{helloworldview} will be a
subclass of the Andrew Toolkit class \italic{view}. \
a hwview.C file -- will contain statements that import Andrew Toolkit
classes and define the class \italic{helloworldview}'s methods and class
procedures. \
a hwapp.H file -- will contain the class definition for the application
program that will display an instance of the \italic{helloworldview}
class
in a window on the workstation. By convention, Andrew Toolkit
application
modules are named \italic{<x>app}, where \italic{<x>} is the name of the
application or an abbreviation for it (e.g., \italic{helloworld}) and
\italic{app} is an abbreviation for the class \italic{application}. \
a helloahwapp.C file -- will contain declarations needed by the Andrew
Toolkit linking and loading facilities as well the definition of an
application method that creates an instance of \italic{helloworldview},
creates a window, puts the object in the window, and enters an
interaction
loop. \
Imakefile -- will contain the directions for compiling, linking and
loading
the modules. \
}}
For a complete listing of these files, see $ANDREWDIR/examples/ex1/*.
On
a first reading of this section, you may find it useful to skim the
program
listing, then refer to the listing when needed as you study how to build
the program. The compiled program is also available in the directory
/usr/andrew/examples/ex1. \
Although the discussion of the steps refers directly to this example, the
information applies generally to the creation of any class or inset that
will be used in a \indexi{Stand-alone application} and to the creation of
any stand-alone application. \
\section{Running the example program}
Before reading the discussion of the example program, you may find it
helpful to run the program on your workstation.
\formatnote{\bold{Action 1:}
\bold{command }prompt type
\formatnote{To run the program, at the
\bold{\leftindent{/usr/andrew/examples/ex1/helloworld}}
and press the Enter key.
}
\bold{Response: }The program will produce a window with \italic{hello
world}
centered in the body as in this figure
\center{
\
\begindata{raster,539010728}
2 0 68266 68266 0 0 183 138
bits 539010728 183 138
zi |
zh02 |
2a/aa$aaa4 |
zh0a |
2a/aa$aaa4 |
12492492492492
49249249249249
09249249249249
24924924924924
24924924924924
92492492492492
11041041041041
04104104104104
2228a28a28a28a
28a28a28a28a28
09451451451451
45145145145145
1228a28a28a28a
28a28a28a28a28
24f2105efa1041
04104785e84107
12f4a52e38a52a
52a52bd2f294aa
0472124f7d1244
91124791e44915
28f4a49e384929
24a493a4f124a3
057f178f7afbef
7bcf7796e48915
287faede3cccef
3763b3afe92425
0573ddef79eef7
6e7bd79de4494d
12779fce3bcf77
7ef383bce9!22
24f3dc5eb9eef7
4f7bd7dee49114
24924924924924
92492492492492
49249249249249
10410410410410
a28a28a28a28a2
14514514514514
a28a28a28a28a2
11610410410410
a58a52a52a52a5
11612449112449
a6ca4924a4!92
55d1c753492044
a2862aeae48a92
55ed7315185124
ea8aaaa6e28a12
d96c558d944144
924a |
4914 |
24a2 |
4114 |
8a22 |
514c |
8a12 |
4144 |
!2a |
1144 |
4a0a |
9154 |
!22 |
948c |
4252 |
9104 |
12779e8f3bde3b
097bdc5e79cf7f
2473afcf3aee19
09Gcfbf7d795d
12509080!4a12
248a2455209144
021049224a4228
294a9249249485
04222124911128
29494a110a4885
0224114a512252
2912a420889488
0449094a522225
29224422094948
2adab5daf6aaab
!555a552a#aaa5
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
ee77a39cf244a2
cf7397bee42915
ae77a3cfe94224
87c7!d772294d
a8aa4408549210
221129450244a5
94a44128548884
22129485212529
44a412288a4842
29094492509294
40a49244852210
9511249250494a
!2488490a9210
!492510a124a5
!555ad6ad!555d
5556!aaa6"aaab
22cb72d2112a12
7954550fa51564
a5a6b3a2aadab2
21494d55459544
1552a4a15214a8
4209111424a205
94!a4a14888a8
!210914!251214
148a5222904824
a25088944a9289
84852521240924
51284894895249
8a!21!2241248a
21!4a49489442
"5556ab5d56ea |
5552aa94 |
24aa |
9214 |
44a2 |
9114 |
!4a |
1094 |
a242 |
94 |
a24a |
1114 |
4a22 |
214a |
24 |
5114 |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
k0180g1980k30
k0180g1980k30
k0180g1980k30
k0180g1980k30
k01bc1e1987c0
k01fe3f198fe0
k01c661998c60
k018661999830
k01867f999830
k018660199830
k018660199830
k018671998c60
k01863f998fe0
k01861e1987c0
zi |
zi |
zi |
v04l |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
v04l |
zi |
06l |
06l |
06l |
06l |
18c61f0db0f6l
18c63f8db1fel
18c6318e318el
0ccc60cc3306l
0ccc60cc3306l
0d2c60cc3306l
052860cc3306l
0738318c318el
03303f8c31fel
03301f0c30f6l
|
|
|
|
|
|
|
|
|
|
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
zi |
\enddata{raster, 539010728}
\view{rasterview,539010728,32,0,0}.}
\bold{Action 2:} Re-shape the program's window.
\bold{Response:} The object will respond to an update request and redraw
\italic{hello world }in the center.
\bold{Action 3: }Click with a mouse button.
\bold{Response: }The program will make no response. This simple object
does not respond to keyboard or mouse input and has only the Quit menu
item. Later examples will illustrate how to extend the program so that
the
view responds to user input.
\bold{Action 4: }To quit the program, select \bold{Quit} from the
\bold{helloworld} menu.
\bold{Response:
}The program will disappear from the screen.
}\
\begindata{bp,539549576}
Version 2
n 0
\enddata{bp,539549576}
\view{bpv,539549576,19,0,0}
\section{Creating a class}
Creating a class \indexi{Class++Creating} in the Andrew Toolkit involves
two steps: \
\enumerate{
\leftindent{Declaring the class as a subclass of an Andrew Toolkit class
Writing class procedures and methods for the class. \
}}
\subsection{The Andrew Toolkit class View} \indexi{View}
\indexi{Class++View
}
In the next section, we will define the class \italic{helloworldview} to
be
a subclass of the Andrew Toolkit class \italic{view}. The class
\italic{view} is at the heart of the Andrew Toolkit. It provides the
methods, class procedures and data structures needed to (1) display a
data
object in a window, (2) request display updates and respond to such
requests, and (3) respond to mouse and keyboard inputs. Thus, to create
any class that interacts with the user, you should declare it as a
subclass
of \italic{view}. \
To simplify the exposition, Example1 does not include a data object and
does not not respond to mouse and keyboard inputs, but it does respond to
requests to update the display. In general, you will want to create a
view-data object pair (called an inset) or some hierarchy of insets, and
an
application module to run/display the program. Insets will be discussed
in
greater detail in Examples 10 and 11. \
\subsection{Choosing a name for a class} \indexi{Class++Naming}
\indexi{View++Naming}
The first step in creating a class is to pick a name for the class. The
name is important for two reasons. First, most Toolkit objects are
loaded
dynamically. \indexi{Dynamic loading} When the Andrew Toolkit encounters
the name of a class to load dynamically, it searches for the class along
a
class path, a path that specifies a list of directories to search. Thus,
if you want to avoid the Toolkit finding the wrong class, the name you
pick
should be unique and not conflict with already existing ones. The second
reason the name is important is that, for some classes, in particular,
for
classes that are data objects, \indexi{Data object++Naming} the user will
sometimes type the class name in order to obtain an instance of it. For
example, the user types the name of a class in order to dynamically load
an
instance of it into the Andrew Toolkit-based editor, \bold{ez}. In such
cases, the name should be memorable for users. Since the class in
Example
1 is not a data object, it need only be unique, not memorable. We chose
the class name \italic{helloworldview}. \
You should also pick a filename for the class. The easiest filename to
use
is, of course, the class name itself. However, for portability, filenames
should be no longer than eight characters. If the class name is longer
than
eight letters, you should pick a shorter abbreviation to use as the
filename. We chose the filename \italic{hwview} for the class
\italic{helloworldview}. (The abbreviation is used only for files; the
methods for this class and the name used to invoke it will still be
\italic{helloworldview}.) \indexi{Class++Filename}
There is no direct way to tell if the class name you chose is already
being
used. However, you can see whether the \italic{filename} you picked is on
your class path. \indexi{Class path} In the \bold{command}, type: \
\leftindent{\bold{whichdo \italic{<your class filename>}}}
The command \italic{whichdo} \indexi{ \italic{whichdo}} (\italic{which}
\italic{d}ynamic \italic{o}bject) is analogous to the \italic{Unix 4.2
BSD}
command \italic{which} (see \bold{help which} for more information); it
takes a list of class names and looks for the files which the Andrew
Toolkit would dynamically load in response to the names. Each argument
is
expanded if it is aliased, and searched for along the dynamic class path,
\smaller{CLASSPATH}. Both aliases and path are taken from the user's
\italic{.cshrc} file. The following is the recommended class path for
inclusion in a \italic{.cshrc}.: \
\programexample{\leftindent{setenv CLASSPATH .:$ANDREWDIR/lib/atk}
}
With this class path, the Andrew Toolkit dynamic object search will look
in
the \italic{current directory} and in $ANDREWDIR/\italic{lib/atk}. If
you
do not have a class path defined in your \italic{.cshrc}, you will
probably
want to define one. The class path defaults to
$ANDREWDIR\italic{/lib/atk}. \indexi{Class path++Default}
\subsection{Declaring a class} \indexi{Class++Declaring} \indexi{Class
declaration}
To create a class, you should declare the class in a \italic{.H}, or
header
file, that has the filename you have chosen for your class. (Note that
the
file extension \indexi{File extensions} is by convention \bold{ .H},
not\bold{ .h}). Thus the class declaration for the class
\italic{helloworldview} is in the file \italic{hwview.H.}
The following is the declaration for the class \italic{helloworldview},
from the file hellov.ch:
\example{class helloworldview: public
view \{
public:
virtual ATKregistryEntry *ATKregistry();
void FullUpdate(enum view_UpdateType type, \
long left, long top, long width, long height);
\};}
The declaration specifies that a class, named \italic{helloworldview,}
is
to be a subclass of the Andrew Toolkit class \italic{view}. One method,
\italic{FullUpdate}, will override \indexi{Override}
\indexi{Methods++Overriding} the class \italic{view}'s
\italic{FullUpdate}
method, which it otherwise would have inherited. No other methods,
special
class procedures, or data are necessary in the class declaration for this
simple example. \
\subsection{Class hierarchies and inheritance} \indexi{Class hierarchy}
\indexi{Inheritance} \indexi{Class++Hierarchy}
In the Andrew Toolkit, classes form a hierarchy. Derived classes
\indexi{Subclass} inherit the methods and data structures of their
parent,
or "base" class. \indexi{Superclass}
Although \italic{helloworldview} declares no methods or data, it inherits
the methods and data from its parent base classes. The class
\italic{view}, \italic{helloworldview}'s immediate parent, is part of the
class hierarchy, \italic{basicobject}, \italic{observable},
\italic{view},
depicted as
\formatnote{
\center{ATK
|
v
traced
|
v
observable
|
v
view
|
v
helloworldview}
}
Therefore, \italic{helloworldview} inherits the methods and data
structures
of \italic{ATK}, \italic{traced}\italic{, observable} and \italic{view}.
For example, \italic{view} provides the method\italic{ Hit}, which will
be
called when the user clicks with the mouse on the left or right button.
Because \italic{helloworldview} does not override \italic{Hit}, it will
inherit view's Hit method. So, when the user clicks with the mouse in a
window containing a \italic{helloworldview} object, the Andrew Toolkit
\italic{Interaction Manager}, which manages interaction events, will call
the \italic{Hit} method \italic{helloworldview} inherits from view, which
does nothing in response to a mouse hit, so the \italic{helloworldview}
object in this example will not respond to mouse hits. Example 3 will
show
how to override \italic{view}'s method so that the class
\italic{helloworldview's} instances will respond to mouse hits. \
In general, you will declare a class as derived from a base class.
\indexi{Class declaration} \indexi{Subclass} \indexi{Superclass} Fail all
else, your object can derive from the \italic{ATK} class at the top of
the
Andrew Toolkit class hierarchy. \
\subsection{Accessing data structures for a class} \indexi{Data
structure++Access}
You access a field defined in a subclass \indexi{Subclass} in the same
way
you access one in a normal C structure.
For example, given a pointer,
\indexi{Class++Pointer to} \italic{hwv}, to the object's
\italic{helloworldview struct}, you would write \italic{hwv->view} to
access the field \italic{view}. \formatnote{(Later examples will
introduce
examples in which accessing fields in the structure is useful.})
To access a field defined in a superclass, \indexi{Superclass} you should
use the class' access method for the field if one is defined. An access
method \indexi{Class++Access method} is simply an encapsulation of a
reference to the field. By using the access method, you avoid making
your
subclass dependent on implementation details of the Andrew Toolkit (This
is
especially important since the implementation might change). If an
access
method for the field is not defined and you really need to access it, you
usually can because most fields are have the "public" attribute. For
example, if you needed to find out how many observers a particular
\italic{helloworldview} object had, you might need to access the class
\italic{observable}'s \italic{nObservers} field. There is no access
method
defined for it. (Since access methods are defined for most fields which
you will need to access, you should spend some time thinking about
whether
there is a better way to do what you want to do). Given a pointer,
\italic{hwv}, to the object's \italic{helloworldview struct}, you would
write \italic{hwv->nObservers}. \
\subsection{Writing class methods} \indexi{Class++Methods}
\indexi{Methods}
Up to this point, we have seen how to declare a class. In this section,
we
discuss how to write class methods and illustrate it by writing a class
method for \italic{helloworldview} that allows it to respond to requests
from the Andrew Toolkit \italic{Interaction Manager} to update the
screen. \
A \italic{method} is like a C procedure, except for how it is invoked.
The
method name is treatd like a field of an object of that class. Thus the
\italic{Update} method of object \italic{hwv} is called with the syntax
\example{hwv->Update(...)}
If the object itself does not define the method, the method is used from
the nearest base class which does define the method. In the case of
\italic{hwv->Update}, the method actually called would be that provided
by
the \italic{view} class.
Methods increase the understandability of your code because they allow
you
to create useful data abstractions \indexi{Data abstraction} that hide
implementation details. For example, suppose you are writing an
application in which you defined an abstract data type, \indexi{Abstract
data types} linked list, consisting of the data \italic{Element} and the
operations, \italic{InsertElement}, \italic{DeleteElement} and so forth.
At the level of data abstractions, you would be dealing with a single
data
element and a set of operations. In a conventional programming language
like C, however, you might need to create several actual data types and
duplicate sets of procedures to implement a single abstract data type.
For
example, suppose that you needed to work with both strings and integers.
In that case, you would need to define two types of arrays, an array of
\italic{int}s and an array of \italic{char*}, and create two procedures
for
the \italic{InsertElement} operation, the one \italic{InsertInteger} and
the other \italic{InsertString}. When you called these procedures, you
would use the two different procedure names. Thus, in the
implementation,
you lose the data abstraction. An object-oriented system allows you keep
the useful abstract representation. You would still need to
\italic{write}
two methods, one for integers and one for strings. But you could set
your
program up so that you could \italic{use the same method name}, for
example, \italic{InsertElement}, to invoke both methods.
\indexi{Methods++Naming}
\paragraph{Calling a method} \indexi{Methods++Calling}
The call to a method is actually an indirect call via the list of methods
attached to an instance of the class. Thus, when you call
\italic{hwv->}\italic{MoveTo}, the \italic{MoveTo} method actually called
is in a field of a list pointed to from the \italic{hwv} object.
In general, for any object \italic{x} in \italic{classx}, (\italic{i.e.},
class\italic{ classx *x)}, you call \italic{methodname (x,
x->methodname(<parameters>)} in order to call either a method for object
x
or a method for any of \italic{x}'s superclasses. Thus, for object
\italic{hwv} in the class \italic{helloworldview}, you write
\italic{hwv->}\italic{GetVisualBounds(<parameters>)} to call the
\italic{view} method \italic{GetVisualBounds}. \
\subsection{Writing a class method for full update requests} \indexi{Full
update} \indexi{Methods++Full update}
When you subclass an already existing Andrew Toolkit class, you will want
to write methods that respond to the requests for which the class
provides
methods. For example, when you subclass \indexi{Subclass} the Andrew
Toolkit class, \italic{view}, you will typically want to write methods
that
respond to requests to update the screen, to handle keyboard input, and
so
forth. In this example, \italic{helloworldview}, we will write a method
that responds to requests to update the screen. Later examples will
introduce further \italic{view} methods. \
Whenever the user takes an action that requires the
\italic{helloworldview}
object's window to be redrawn, the Andrew Toolkit \italic{Interaction
Manager} will call the \italic{FullUpdate} method. The method should do
whatever it must do to redraw the display. \indexi{Redraw} In this
example, when \italic{helloworldview's FullUpdate} gets called, we would
like it to draw the string \italic{hello world} in the center of the
window. \
To write the \italic{FullUpdate} method, you should declare it in a
\italic{.C} file that has the same name as your class. The declaration
for
the \italic{helloworldview}'s \italic{FullUpdate} method is in the file
\italic{hwview}\italic{.c.} The following is the \italic{FullUpdate}
method in its entirety, followed by a detailed explanation of its various
parts: \
\programexample{
}\example{\programexample{
void \
helloworldview::FullUpdate(enum view_UpdateType
long
left, long
top, long
type, \
width, long
height) \{
int x,y;
struct rectangle VisualRect;
\
GetVisualBounds(&VisualRect);
x = rectangle_Left(&VisualRect) + rectangle_Width(&VisualRect)/2;
y = rectangle_Top(&VisualRect) + rectangle_Height(&VisualRect)/2;
MoveTo(x,y);
DrawString("hello world",
graphic_BETWEENTOPANDBASELINE |
graphic_BETWEENLEFTANDRIGHT);
\}}
}
\paragraph{Parameters and method definitions}
Whenever you override a superclass' method, you must use the same
parameters in the method definition as in the superclass.
\indexi{Overrides}
\indexi{Superclass} \indexi{Parameters} \indexi{Methods++Parameters}
\indexi{Methods++Overrides} For example, the following are the
parameters
for view's \italic{FullUpdate} method: \
\programexample{\leftindent{enum view_UpdateType
type \
long
left \
long
top \
long
width \
long
height}}
The \italic{FullUpdate} method has five parameters: \italic{type}, the
type of redraw and \italic{left}, \italic{top}, \italic{width} and
\italic{height}, the limits of what needs to be redrawn. The last five
parameters allow you to optimize the redraw. We will ignore them in this
simple example. \
\paragraph{Drawing on the screen: The class 'graphic'} \indexi{Drawing}
\indexi{Graphic} \indexi{Class++Graphic}
Responding for a request to update the screen requires drawing on the
screen. The Andrew Toolkit has a class, \italic{graphic}, that provides
the class procedures and methods necessary for drawing. Thus, to
understand how to do a \italic{FullUpdate}, it is necessary to introduce
some graphic concepts. \
The class \italic{graphic} provides an output interface to
hardware-dependent window management systems. \indexi{Window managers}
As
an application programmer, you should understand why application programs
should not display their pictures directly to an underlying window
management system: application programs must often be ported to other
workstations that will eventually be deployed. The workstations often
have
similar, but not identical display capabilities and the hardware can be
significantly different; the underlying window manager may be different.
To insure portability \indexi{Application program++Portability} of your
application, you should never make direct calls to an underlying window
management system; you should always use the \italic{graphic} class
procedures and methods; doing so will maximize the device independence
and
portabilty of your application program. \
You should use instances of the class \italic{graphic} to do output to
workstation displays. For example, to draw text and put box around it,
you
would make calls to the methods and class procedures provided by the
class
\italic{graphic}. The class graphic provides methods for drawing lines,
shapes, and text. It also provides methods for transferring entire
blocks
of bits. \
\formatnote{\italic{View interface to graphic}} \indexi{Class++View}
\indexi{Graphic++View interface}
\indexi{Class++Graphic}\indexi{View++Graphic macromethods}
Each \italic{view} object has an associated \italic{graphic} object in
which drawing takes place.
In addition, for each method that
\italic{graphic} provides, the class \italic{view} provides a
corresponding
\italic{macromethod}. For example, the class \italic{graphic} provides
the
method \italic{DrawString}, a drawing primitive for drawing text on the
workstation screen. The graphic method \italic{DrawString} requires two
parameters: the text to be drawn on the screen, and a specification of
\italic{how} the text is to be drawn.
The class \italic{view} provides
a
corresponding inline \italic{method} that takes two parameters, the text
to
be drawn and the specification of \italic{how} it is to be drawn. The
\italic{view} method calls the \italic{graphic} method. \
\formatnote{\flushleft{\bold{Graphic rectangles}}}
\indexi{Graphic++Rectangles} \indexi{Rectangles}
Drawing in a graphic is done in relation to rectangles. A
\italic{rectangle} is specified by a point, \italic{(left, top)}, and a
\italic{width} and \italic{height:
\center{\
\begindata{figure,539714152}
$origin 0 0
$printscale 1.000000 1.000000
#none 0
\begindata{figogrp,539715240}
\figattr{
}
$ 0 28 163 2029 837
$endatt
\enddata{figogrp,539715240}
\begindata{figotext,540016520}
attrs: -1 2 10 black 12 0 andysans
$ 332 381
$ 0 0
(x,y)=000
$endatt
\enddata{figotext,540016520}
\begindata{figospli,540020744}
attrs: -1 2 10 black 12 0 andy 0 5
$$ 0 4 0 0
$ 231 313
$ 57 -97
$ 201 -97
$ 345 -25
$endatt
\enddata{figospli,540020744}
\begindata{figotext,540023576}
attrs: -1 2 10 black 12 0 andysans
$ 1609 500
$ 0 0
Height=000
$endatt
\enddata{figotext,540023576}
\begindata{figorect,539973720}
attrs: 1 2 10 blue 12 0 andy 0 8 0
$ 576 288
$ 864 432
$endatt
\enddata{figorect,539973720}
\begindata{figoplin,540010952}
attrs: -1 1 10 black 12 0 andy 0 8
$$ 0 2 0 0
$ 1512 288
$ 144 0
$endatt
\enddata{figoplin,540010952}
\begindata{figoplin,540023800}
attrs: -1 1 10 black 12 0 andy 0 8
$$ 0 2 0 0
$ 1512 720
$ 144 0
$endatt
\enddata{figoplin,540023800}
\begindata{figoplin,540028664}
attrs: -1 1 10 black 12 0 andy 0 8
$$ 0 2 0 0
$ 1440 792
$ 0 144
$endatt
\enddata{figoplin,540028664}
\begindata{figoplin,540029320}
attrs: -1 1 10 black 12 0 andy 0 8
$$ 0 2 0 0
$ 576 792
$ 0 144
2 8 0 5 0
1 5 0
1 5 1 5 0
5 0
0 5 0
0 5 0
0 5 0
0 5 0
$endatt
\enddata{figoplin,540029320}
\begindata{figoplin,540030072}
attrs: -1 1 10 black 12 0 andy 0 5 3 5 0
$$ 0 2 0 0
$ 1584 288
$ 0 432
$endatt
\enddata{figoplin,540030072}
\begindata{figoplin,540032600}
attrs: -1 1 10 black 12 0 andy 0 5 3 5 0
$$ 0 2 0 0
$ 576 864
$ 864 0
$endatt
\enddata{figoplin,540032600}
\begindata{figotext,540033256}
attrs: -1 1 10 black 12 0 andysans 0 5 3 5 0
$ 1008 936
$ 0 0
Width=000
$endatt
\enddata{figotext,540033256}
#end
\enddata{figure,539714152}
\view{figview,539714152,57,376,193}}}
F\formatnote{igure:
\formatnote{(A rectangle)}
}
The Andrew Toolkit defines the following macros for setting the
dimensions
of a rectangle and finding out the values of those dimensions:
\indexi{Rectangles++Size}
\
\leftindent{\formatnote{\italic{rectangle_SetRectSize
dimensions of a rectangle.
\italic{rectangle_Left
\italic{rectangle_Top
---
\italic{rectangle_Width
\italic{rectangle_Height
--
}set the
}get the value of the point, left.
}get the value of the the point, top.
---
}get the width.
}get the height.
}}
In the tutorial, we will introduce these macros as they arise in the
examples. \
\indexi{Rectangles++Logical}\indexi{Rectangles++Visual}
The class \italic{graphic} defines the coordinate system for drawing.
The
units are pixels. \indexi{Pixel} The coordinate space has (0,0) at the
origin on the rectangle's top left to 2\superscript{32}- 1,
2\superscript{32}-1 at its bottom right. You can draw anywhere in this
logical unsigned 32-bit coordinate space.
\indexi{Rectangles++Coordinates}
The logical rectangle, \italic{lr}, specifies the rectangle to which a
view
should scale its drawing. The class \italic{graphic} also provides a
\italic{visual rectangle}, \italic{vr}, that is a subrectangle of the
logical rectangle and gives the coordinates for what is potentially
visible
in the window. To illustrate \italic{logical rectangles} and
\italic{visual rectangles}, the Figure below depicts an inset displaying
some text (\smaller{ZORK}) and a drawing. Note that the drawing happens
to
be at the very bottom of the window and its logical rectangle,
\italic{lr}
falls outside the window boundary. \indexi{Window boundaries} If a
graphic's logical rectangle falls outside the window boundary and the
drawing is relative to \italic{lr}, then the drawing will be clipped to
the
graphic's visual rectangle, \italic{vr}. The part of the drawing that
falls within the coordinates given by the \italic{visual rectangle}
normally corresponds to what the user sees on the screen, except if
another
drawing were laid over the first (e.g., a message box could be
temporarily
laid on top all or part of the drawing). \
\begindata{figure,539014712}
$origin 0 0
$printscale 1.000000 1.000000
#none 0
\begindata{figogrp,539039368}
\figattr{
}
$ 0 280 136 2594 1609
$endatt
\enddata{figogrp,539039368}
\begindata{figotext,539497752}
attrs: -1 2 10 black 12 0 andysans 1 8 0 5 0
$ 1634 469
$ 0 0
Window=040on=040screen=000
$endatt
\enddata{figotext,539497752}
\begindata{figotext,539845352}
attrs: -1 2 10 magenta 14 0 andy 1 8 0 5 0
$ 475 519
$ 0 0
ZORK=000
$endatt
\enddata{figotext,539845352}
\begindata{figorect,539894952}
attrs: -1 4 10 blue 14 0 andy 1 8 0 5 0
$ 720 1008
$ 576 720
$endatt
\enddata{figorect,539894952}
\begindata{figorect,539908312}
attrs: 5 2 10 green 14 0 andy 1 8 0 5 0
$ 720 1008
$ 576 432
$endatt
\enddata{figorect,539908312}
\begindata{figorect,539909912}
attrs: -1 2 10 red 12 0 andysans 1 8 0 5 0
$ 288 1440
$ 1152 -1296
$endatt
\enddata{figorect,539909912}
\begindata{figotext,539965112}
attrs: 1 4 10 black 12 0 andysans 1 8 0 5 0
$ 1584 1152
$ 0 0
Visual=040rectangle=000
$endatt
\enddata{figotext,539965112}
\begindata{figotext,539965528}
attrs: 1 4 10 black 12 0 andysans 1 8 0 5 0
$ 1584 1440
$ 0 0
Logical=040rectangle=012(includes=040visual)=000
$endatt
\enddata{figotext,539965528}
\begindata{figospli,539966200}
\figattr{
shade:1
color:black
linewidth:2
rrectcorner:10
fontsize:12
fontstyle:0
fontfamily:andysans
textpos:1
arrowpos:1
arrow:5
linestyle:0
}
$$ 0 3 0 0
$ 1759 544
$ -100 125
$ -319 176
$endatt
\enddata{figospli,539966200}
\begindata{figospli,539967176}
attrs: 1 2 10 black 12 0 andysans 1 5 2
$$ 0 3 0 0
$ 1327 1195
$ 138 69
$ 238 19
$endatt
\enddata{figospli,539967176}
\begindata{figospli,540082008}
attrs: 1 2 10 black 12 0 andysans 1 5 1
$$ 0 3 0 0
$ 1512 1512
$ -79 78
$ -173 78
$endatt
\enddata{figospli,540082008}
\begindata{figospli,540081016}
attrs: 1 2 10 black 12 0 andysans 1 5 1
$$ 0 4 0 0
$ 1537 1512
$ -104 -4
$ -135 -110
$ -198 -148
$endatt
\enddata{figospli,540081016}
#end
\enddata{figure,539014712}
\view{figview,539014712,58,436,316}
Figure: The logical and visual graphic
5 0
5 0
5 0
rectangles
\formatnote{\bold{Scaling the drawing to the visual rectangle}}
\indexi{Drawing++Scaling} \indexi{Rectangles++Scaling}
\indexi{Graphic++Scaling}
Rather than scaling the drawing to the logical rectangle (and being
clipped), a view can scale its drawing to its graphic's visual
rectangle.
For example, in order to draw the string \italic{hello world} in the
center of the display, \italic{helloworldview} will scale its drawing to
its graphic's visual rectangle. Whenever such a \italic{view} receives a
call to do a \italic{FullUpdate} of its part of the screen, it must call
\italic{GetVisualBounds} \indexi{ \italic{GetVisualBounds
}} \indexi{ \italic{view_GetVisualBounds}}
\indexi{ \italic{graphic_GetVisualBounds}}
\indexi{View++\italic{GetVisualBounds}}
\indexi{Graphic++\italic{GetVisualBounds}} in order to find out the size
of
its graphic's visual rectangle and get its coordinates.
\italic{GetVisualBounds} is a \italic{view} method that takes as its
argument a \italic{struct rectangle}. \italic{GetVisualBounds} sets the
rectangle to the coordinates of the view's graphic visual rectangle.
For
example, in \italic{helloworldview}'s \italic{FullUpdate} \indexi{Full
update} method, the following lines get the coordinates of the visual
rectangle: \
\programexample{\leftindent{ GetVisualBounds(hwv, &VisualRect); \
x = rectangle_Left(&VisualRect) + rectangle_Width(&VisualRect)/2; \
y = rectangle_Top(&VisualRect) + rectangle_Height(&VisualRect)/2; }\
}
The statement, \italic{GetVisualBounds(hwv, &VisualRect)} sets
\italic{VisualRect} to the dimensions of \italic{hwv}'s visual rectangle.
That is, that part of \italic{hwv}'s graphic rectangle that is
potentially
visible in the window. The statements that assign values to \italic{x}
and
\italic{y} calculate the horizontal and vertical centerpoints of the
visual
rectangle. The values of \italic{left} plus the \italic{width} divided
by
two yield the horizontal center point; the values of \italic{top} plus
\italic{height} divided by two yield the vertical. \
\formatnote{\bold{Moving the graphic point and drawing}}
\indexi{Graphic++Point} \indexi{Drawing}
The \italic{graphic} drawing primitives use a \italic{current point} as a
reference point. Drawing is done from the \italic{current point} to a
specified (x,y) coordinate. The method \italic{MoveTo} is a
\italic{view}
method that moves the graphic's \italic{current point} to a specified
coordinate. It takes two arguments, the (x,y) coordinates. The method
\italic{MoveTo} \indexi{ \italic{MoveTo}} \indexi{
\italic{graphic_MoveTo}}
\indexi{ \italic{view_MoveTo}} \indexi{Graphic++\italic{MoveTo}}
\indexi{View++\italic{MoveTo}} moves its object's graphic drawing point
to
(x,y). Before drawing, a \italic{view} should move the drawing point,
then
call a drawing primitive. For example, to draw the string \italic{hello
world} in the center of the window, the following part of
\italic{helloworldview's} \italic{FullUpdate} \indexi{Full update} method
moves the \italic{current point}, then calls a string-drawing primitive:
\
\programexample{\example{MoveTo(x, y);
\
DrawString("hello world",
graphic_BETWEENTOPANDBASELINE |
graphic_BETWEENLEFTANDRIGHT); }\
}
As in all methods, the object to which MoveTo and DrawString apply is the
object to which the FullUpdate method applies. (This object is the value
of the implicit pointer \italic{this}.) The statement, \italic{MoveTo(x,
y)}, moves \italic{this}'s graphic drawing point to coordinates (x,y),
the
center of its's visual rectangle. The next statement,
\italic{DrawString},
\indexi{Graphic++\italic{DrawString}}
\indexi{View++\italic{DrawString}}\indexi{ \italic{DrawString}} is a
\italic{view} method that actually draws \italic{hello world} in the
window
at the center point. The alignment options
\smaller{BETWEENTOPANDBASELINE}
and \smaller{BETWEENLEFTANDRIGHT} are used to center the string around
the
current drawing point as set by the preceding MoveTo. Other alignment
options are available to start the string at point (x,y), to end the
string
at (x,y), and so forth (see \italic{DrawString}, \bold{Graphic.doc}). As
mentioned earlier, \italic{graphic} provides other drawing methods for
drawing lines, polygons, and other shapes. \
\section{Creating a stand-alone application program} \indexi{Stand-alone
application}
At this point, we have defined a complete subclass, \indexi{Subclass}
\italic{helloworldview}. In the Andrew Toolkit, such a class can be used
in one of two ways: (1) It can be paired with a \italic{dataobject}
\indexi{Data object} to form an inset \indexi{Inset} (i.e., a
dataobject/view pair); (2) it can be used in a stand-alone application
program, illustrated in this example. \formatnote{Note: insets can also
be used in a stand-alone application program. (See Example 10)}
\subsection{Applications and the base program, 'runapp'} \indexi{Runapp}
Andrew Toolkit applications are designed to run from a single base
program
called \italic{runapp}, short for \italic{run} \italic{app}lication).
The
program \italic{runapp} contains the code for all the basic components of
the Andrew Toolkit. The program \italic{runapp} dynamically loads the
code
that is unique to individual applications into memory at run time.
\indexi{Dynamic loading}
To understand why this scheme is desirable, it is useful to examine, in
brief, part of the \italic{UNIX} memory management subsystem.
\indexi{Memory management} Each process on the UNIX system consists of
three logical memory regions: text, data, and stack. The text region
contains the set of instructions that the machine executes for the
process;
the data region contains global data; and the stack region contains the
data local to a subroutine. Several processes can share a region; the
most
usual case is that of several processes executing the same program and
sharing one copy of the text region. \formatnote{\
}
The \italic{runapp} scheme is designed to allow Andrew Toolkit
applications
to share significant portions of program code. Shared code leads to
decreased paging activity, decreased page faults (key portions of code
are
almost always paged in), decreased virtual memory use, decreased number
of
file fetches (under a distributed file system), and decreased file size
of
an application. \
\section{The class Application} \indexi{Application}
\indexi{Class++Application}
The class \italic{application} provides an interface between
\italic{runapp}
and application programs. In particular, \italic{application} provides
the
following methods that \italic{runapp} will call when it loads an
application into memory: \
\formatnote{
\leftindent{\italic{ParseArgs(int argc,char **argv); -- }A method that
should parse the command line arguments for the application. Returns
boolean. \indexi{ \italic{ParseArgs}} \
\italic{ReadInitFile(); -- }A method that should read any
initialization
files for the application. \indexi{ \italic{ReadInitFile}}
\italic{Start(); -- }A method that should set-up the application so
that
it can start running (e.g., create instances of classes, windows, etc.).
Returns boolean. \indexi{ \italic{Start}} \
\italic{Run(); -- }A method that actually begins running the
application.
Returns int. \indexi{ \italic{Run}}
\italic{Fork(); -- }A method that frees the typescript when not
debugging. Returns boolean. \indexi{ \italic{Fork}}}
}
The program \italic{runapp} \indexi{Runapp} calls these methods when it
loads an application into memory. In particular, it calls
\italic{ParseArgs} to request the application to parse any command line
arguments it may have, then call \italic{ReadInitFile} to request the
application to read its initialization file, if any, then calls
\italic{Start} to request the application program to create and
initialize
its objects and window, and finally calls \italic{Run} which (if not
debugging), calls the method \italic{Fork} and enters the
\italic{Interaction Manager's} keyboard interaction loop that mediates
communication between a user and the application. \
Thus, to set up as a stand-alone application program, you should create a
class that is a subclass of the Andrew Toolkit class,
\italic{application}.
The \italic{application} subclass should override those
\italic{application} methods that you need. For example, for simplicity
of
exposition, this introductory example has no command line arguments or
initialization files, so it does not need to override \italic{ParseArgs}
or
\italic{ReadInitFile}. Nor does it need to override the method
\italic{Run}
or \italic{Fork}. Thus, the only override we need to make is to
\italic{application}'s \italic{Start} method, the method that should
create
instance of classes (e.g., an instance of \italic{helloworldview}, create
a
window, and so on. \
In this example, we create a subclass, \italic{helloworldapp}, in the
file
\italic{hwapp.H}. By convention, Andrew Toolkit application modules are
named \italic{<x>app}, where \italic{<x>} is the name of the application
or
an \indexi{Application++Naming} \indexi{Application++Modules}
\indexi{Application program} abbreviation for it (e.g.,
\italic{helloworld}) and \italic{app} is an abbreviation for the class
\italic{application}.
\programexample{
\example{class helloworldapp : public
application \{
public:
virtual ATKregistryEntry *ATKregistry();
boolean Start()
;
\};}
}
\subsection{Writing a 'Start' method} \indexi{ \italic{\
Start}}
To create a stand-alone application program, you must write a
\italic{Start}
method. The program \italic{runapp} will call your \italic{Start} method
in order to run your program. Basically, the method should create an
instance of the class, create a window, put the object in the window.
For
example, for \italic{helloworldview}, the application's \italic{Start}
method should create an instance of the class \italic{helloworldview},
create a window, and put the \italic{helloworldview} instance in the
window. \
To write the \italic{Start} method, you should declare it in a
\italic{.C}
file that has the same name as your application class. The following is
the declaration for \italic{helloworldapp}'s \italic{Start} method is in
the file \italic{hw}\italic{app.c}, followed by a detailed explanation of
its various parts: \
\programexample{
\example{boolean helloworldapp::Start()
\{
class helloworldview *hwv;
class im *im;
if( ! application::Start())
return FALSE;
hwv = new helloworldview;
if(hwv == NULL)
return FALSE;
im=im::Create(NULL);
if(im == NULL)\{
(hwv)->Destroy();
return FALSE;
\}
(im)->SetView(hwv);
(hwv)->WantInputFocus(hwv);
return TRUE;
\}}
}
\paragraph{Initializing the application}
The first statement in an application's \italic{Start} method should be a
call to itsbase class's \italic{Start} method.
\programexample{\example{
if( ! application::Start(hwapp))
return FALSE; }\
}
In this case, the call executes \italic{application}'s \italic{Start}
method, which initializes to default values the foreground and background
colors for graphics. If the call is unsuccessful, you should return
\smaller{FALSE}. \
\paragraph{Creating an instance of a class} \indexi{Class++Creating}
Most applications will create instances of objects that they will be
using.
In general, to create an instance of a class, you apply the \italic{new}
operator to the class name. For a class \italic{x}, you call
\italic{new}
\italic{x}. To create an instance of helloworldview, you write
\programexample{
\example{hwv = new helloworldview;
if(hwv == NULL)
return FALSE;}
} \
The \italic{new} operator creates an instance of the class
\italic{helloworldview} which is then assigned to \italic{hwv}. If
\italic{hwv} is \smaller{NULL}, the \italic{new} was unsuccessful and you
should return \smaller{FALSE} (\italic{i.e.}, failure). \
\paragraph{Creating an Interaction Manager and a window}
In addition to creating an instance of a class, a stand-alone application
will want to create an \italic{Interaction Manager}, an instance of the
Andrew Toolkit class \italic{im} that manages the communication between
the
underlying window manager and views. As a side effect, creating an
\italic{Interaction Manager} creates a window using whatever window
manager
is running on the workstation. Currently, the Andrew Toolkit runs on the
X
window system. There is one \italic{Interaction Manager} per window.
\indexi{Windows} \indexi{Window manager} \indexi{Interaction manager}
\indexi{View++Interaction manager}
For example, the following creates an \italic{Interaction Manager},
\italic{im}, for the helloworldview application, \italic{helloworldapp}:
\
\example{im=im::Create(NULL);
if(im==NULL)\{
(hwv)->Destroy();
return FALSE;
\}}\programexample{
}
The call to \italic{im::Create(NULL)} creates an \italic{Interaction
Manager} (\italic{im}) view and, as a side effect, creates a window using
whatever window manager is running on the workstation.
If \italic{im} is \smaller{NULL}, then the attempt to create the
\italic{Interaction Manager} was unsuccessful and you should destroy any
objects, (e.g., \italic{hwv}) and return \smaller{FALSE}, \italic{i.e.},
failure. \indexi{Objects++Destroying}
\subsection{The view tree} \indexi{View tree} \indexi{View}
The \italic{im} view is the root of the window's view tree. Recall that
views represent space on your computer's display screen. Views are
organized into trees. \italic{hmv->SetView (im)} puts \italic{hwv} in
the
view hierarchy with \italic{im}, which happens to be the root view, as
the
parent. The screen space assigned to a view is always totally included
within the screen space allocated to its parent view. Two sibling views,
however, may find their screen space overlapping in any way, as long as
both siblings are contained within their parent's screen space
allocation. \
It is important to understand the difference between the Andrew Toolkit
class hierarchy and a view hierarchy. The class hierarchy defines a
\indexi{Class hierarchy} \indexi{Class++Hierarchy} tree of base-class /
derived-class relationships among classes; the view hierarchy defines a
tree of \italic{view objects}, i.e., actual instances of the class
\italic{view}. In the class hierarchy, defined through the statements
\bold{class} <class name> \bold{\bold{:}} <super-class>, both the Andrew
Toolkit class \italic{im} and the class \italic{helloworldview} are
subclasses of the class \italic{view;} in the view \indexi{Superclass}
\indexi{Subclass} hierarchy, defined by calls to \italic{im::SetView},
\indexi{Interaction manager++\italic{SetView}}\indexi{ \italic{SetView}}
the view \italic{hwv}, an instance of class \italic{helloworldview, }is a
child of the view \italic{im}, an instance of the class \italic{im}. \
\subsection{The interaction loop} \indexi{Interaction manager}
\indexi{Interaction loop}
After calling an application's \italic{Start} method, \italic{runapp}
calls
the application's \italic{Run} method. \indexi{ \italic{Run}} In this
example, \italic{helloworldapp} inherits \italic{application}'s
\italic{Run}
method, which frees the \bold{command} (provided the debugging flag is
not
set) and calls \italic{im::KeyboardProcessor}. \indexi{Interaction
manager++\italic{KeyboardProcessor}}
The call to \italic{im::KeyboardProcessor()} enters the
\italic{Interaction
Manager}'s interaction loop, which mediates communication between a user
(and the underlying window system) and the view(s) in the view tree
(e.g.,
helloworldview). Logically, the interaction loop can be thought of as
having the following pseudo-code structure: \
\programexample{
\example{while (there is not an exit signal)
if a timed event on the event queue is scheduled to happen at this
time: \
call the event handler;
else if there is user input pending: \
call the child's appropriate method; \
else if there is file I/O on a file: \
call the appropriate file I/O handler; \
else if the user has done something that requires a full update of
the
screen: \
call child's FullUpdate method; \
else if there are requests for updates on the want update list: \
call the child's Update method; \
else if there is a child process that has died: \
release the child process to allow reuse of its resources; \
else
wait for an event; \
end /* while */
}}
In general, you will not need to override \italic{application}'s
\italic{Run} method. If you do override it, however, note that a call to
\italic{im::KeyboardProcessor} will normally be the last statement in the
\italic{Run} method, since once the interaction loop is entered,
subsequent
calls will not be processed until the loop is exited. \
\section{Makefiles and compiling} \indexi{Compiling} \indexi{Makefile} \
Andrew utilizes the imake system from the X system, but with its own set
of
macros and conventions. For the helloworld application the following is
sufficient in the Imakefile:
\leftindent{OBJS = hwapp.o
HFILES = hwapp.H
hwview.o
hwview.H
DIRX = $(DESTDIR)/examples
MkdirTarget($(DIRX) $(DIRX)/ex1)
ATKLibrary(ex1, $(OBJS), , , )
RunappWithLibrary(helloworld,ex1, -r .) \
InstallProgram(helloworld,$(DIRX)/ex1)
InstallExampleClassFiles($(HFILES), $(DIRX)/ex1)
InstallDocs(ex1.doc, $(DIRX)/doc)
}
The \italic{Makefile} \indexi{Makefiles} \indexi{ \italic{make}} for a
class that will stand-alone is for the most part, like any other
\italic{Makefile} (see \italic{make} in the online help pages). This
particular Makefile creates the dynamically loadable versions of
helloworldapp and helloworldview from the corresponding .o and .eh files.
The respective .o and .eh files also depends on information in the
corresponding .c and .h files and from .ih files of all classes that
provide necessary information to this particular application
(application,
graphic, view, observable, im, point, rectangle). The list of classes
that
need to be included in the dependencies list is determined by each
individual application -- the rule of thumb is to include all classes
that
are explicitly called, their parents and ancestors, and any other
non-classes (such as point and rectangle) that provide information to the
classes. Note that class.h must also be included to create the .o and
.eh
files. \
The Imakefile given above will succeed on any platform. On some
platforms
it may be quicker to create a dynamically loadable object. To do this,
replace the three lines ATKLibrary ... InstallProgram with these lines:
\example{DynamicMultiObject(helloworldapp, helloworldview, $(OBJS),,,)
InstallDynamicObject(helloworldapp, helloworldview, $(DIRX)/ex1) }\
Before running the resulting program, the directory containing the output
must be listed in the value of the CLASSPATH environemnt variable. For
most cases the CLASSPATH value can be .:$ANDREWDIR/lib/atk, where the
initial dot adds the current directory to the list. Then the program is
executed from the build directory with the command
runapp helloworldapp
\subsection{Compiling and linking the class and the program}
To compile the class and the program using the \italic{Imakefile}, you
should have that file and the files \italic{hwview.H},\italic{
hwview\italic{.}}\italic{C}, \italic{hwapp}\italic{.H}, and
\italic{hwapp}\italic{.C }in a single directory to which you have read,
write and list permissions. You may copy these files from
/usr/andrew/examples/atk/ex1. \
Go to the directory in which you have put the files (that is, make it the
current directory). Then at the command prompt, type
\example{cp /usr/andrew/examples/ex1/* . }\
You will also need to change the protections on the files to +w:
\leftindent{\example{chmod +w *}}
(For more information on file protections, see \italic{chmod} in the
online
help pages.) \
Then check that ANDREWDIR is set properly in your environment variables
and
that $ANDREWDIR/bin is on the list given by the PATH environment
variable.
Finally, compile and link the program thusly:
\example{\leftindent{genmake}; make}
\subsection{Running an application}
Andrew Toolkit applications are designed to run from a single base
program
called \italic{runapp}, short for \italic{run} \italic{app}lication).
The
program \italic{runapp} actually dynamically loads the application into
memory. \indexi{Runapp} \indexi{Application program++Running}
To run after compilation, type: \
\example{./helloworld}
and the window will appear.
\begindata{bp,539796616}
Version 2
n 0
\enddata{bp,539796616}
\view{bpv,539796616,31,0,0}
Copyright 1992, 1996 Carnegie Mellon University and IBM.
reserved.
All rights
\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,539494632}
Download