double newton( double arg ) { // computes square root double r=arg, x=1, eps=0.0001; while( fabs(r - x) > eps ) { r = x; x = r - (r * r - arg) / (2 * r); } return r; }
#!/usr/prac/se/bin/hush -f proc generate {} { .m configure -text [.s get] } scale .s -label "seed" -orient horizontal -relief sunken message .m -width 256 -aspect 200 pack .m .s -fill x bind .s <Any-ButtonRelease> { generate }
// Initial declarations #include "hush.h" double newton(double arg); // declare the function char* ftoa( double f); // to convert float to char* // The generator (handler) class gives access to the widgets class generator : public handler { public: generator() { // access to Tcl widgets s = (scale*) new widget(".s"); m = (message*) new widget(".m"); } ~generator() { s->destroy(); m->destroy(); // to destroy widgets delete s; delete m; // to reclaim resources } int operator()() { // the generator action float f = s->get(); m->text( ftoa( newton(f) ) ); // display value return OK; } private: scale* s; message* m; }; // The application class takes care of installing the interface class application : public session { public: application(int argc, char* argv[]) : session(argc,argv,"newton") {} void main( ) { // tk is an instance variable tk->source("interface.tcl"); // read interface script handler* g = new generator(); tk->bind("generate",g); // bind Tcl command } }; // Finally, the function main is defined void main (int argc, char **argv) { session* s = new application(argc,argv); s->run(); }
hush.h
header file and declare
an auxiliary function ftoa
that is used to convert floating point
values to a string.
The next step
involves the definition of the
interfacing between the Tcl code
and the C++ program.
The class generator defines
a so-called handler object that will
be associated with the function
generate employed in the script,
overriding the dummy Tcl function generate
as defined in the script.
In order to access the scale and message widget
defined for the interface, C++ pointers to
these widgets are stored in instance
variables of the object.
These pointers are initialized when
creating a generator object.
The widgets
are destroyed when deleting the object.
Note that the widgets must first
be destroyed before deleting the corresponding C++
objects.
All you need to know at this stage is
that when the function generate
is called in response to moving
the slider,
or more precisely releasing the mouse
button,
then the operator() function of the
C++ generator object is called.
In other words, the operator()
function is (by convention)
the function that is executed
when a Tcl command that is bound
to a handler object is called.
The generator::operator() function
results in displaying
the outcome of the newton function,
applied to the value of the slider,
in the message widget.
Then we
define an application class,
which is needed for the program to
initialize the X-windows main event loop.
An application class must be
a subclass of the session class.
To initialize the program,
the application class redefines
the (virtual) function main
inherited from session.
The function application::main takes
care of initializing the interface,
creates an instance of the generator
class,
and binds the Tcl command generate
to the generator object.
Finally, the function main is defined.
A function main is required for each C or C++
program.
It consists merely
of creating an instance of the application class and the
invocation of run, which starts
the actual program.
#include "hush.h" // Include definitions of external package(s) #include "extern/ht.h" // Define the application class class application : public session { public: application(int argc, char* argv[]) : session(argc,argv) { hyper = 0; if ((argc==3) && !strcmp(argv[1],"-x")) { // check for -x hyper = 1; strcpy(hyperfile,argv[2]); } } void main() { // tk represents the kit init_ht(tk); // initialize package(s) if (hyper) { // initialize hypertext hypertext* h = new hypertext(".help"); h->file(hyperfile); h->geometry(330,250); h->pack(); tk->pack(".quit"); // predefined button to quit } } private: char hyperfile[BUFSIZ]; int hyper; }; // Define the main function int main (int argc, char* argv[]) { session* s = new application(argc,argv); s->run(); // start X event loop }
interface kit { int eval(char* cmd); // to evaluate script commands char* result(); // to fetch the result of eval void result(char* s); // to set the result of eval char* evaluate(char* cmd) // combines eval and result int source(char* f); // to load a script from file void bind(char* name, handler* h); // to bind Tcl command widget* root(); // returns toplevel (root) widget widget* pack(widget* w, char* options = "-side top -fill x"); widget* pack(char* wp, char* options = "-side top -fill x"; char* selection(char* options=""); // X environment void after(int msecs, char* cmd); void after(int n, handler* h); void update(char* options=""); char* send(char* it, char* cmd); void trace(int level = 1); void notrace(); void quit() // to terminate the session };
interface session { session(int argc, char** argv, char* name = 0); virtual void prelude(); virtual void main(); int run( ); protected: kit* tk; };