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;
};