#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <X11/Intrinsic.h> #include <X11/StringDefs.h> #include <X11/IntrinsicP.h> #include <X11/Xaw/Command.h> #include <X11/Xaw/Box.h> #include <X11/Xaw/Form.h> #include <X11/Xaw/AsciiText.h> #include <tcl.h> #include <tk.h> Tcl_Interp *interp; Display *dis; int screen; #define winIdLength 16 void PressMe () { fprintf (stderr, "You pressed me.\n"); } void Action () { fprintf (stderr, "Now I'm going to exit.\n"); exit (0); } void addTkToplevelToXtBox (char *winName, Widget parent) { char tCmdg = "toplevel $winName -use $winId"; char winId[winIdLength]; sprintf (winId, "%ld", XtWindow (parent)); Tcl_SetVar (interp, "winName", winName, 0); Tcl_SetVar (interp, "winId", winId, 0); if (Tcl_Eval (interp, tCmd) != TCL_OK) { fprintf (stderr, "Error evaluating tCmd within addTkToplevelToXtBoxCmd() %s", Tcl_GetStringResult (interp)); } } Widget addXtBox (char *wClass, Widget wParent) { return (XtVaCreateManagedWidget ( wClass, boxWidgetClass, wParent, NULL, 0) ); } void makeXtBoxFitToplevel (Widget wid, char *winName) { Tk_Window twin = Tk_NameToWindow (interp, winName, Tk_MainWindow (interp)); Tcl_Eval (interp, "update idletasks"); XtResizeWidget (wid, Tk_Width (twin), Tk_Height (twin), 1); XFlush (dis); } int main (int argc, char *argvg) { Widget win, button; Widget testButton; Widget buttonShell; Widget xtBox2; Widget entry; XEvent event; XtAppContext appContext; char entryBuffer; Tcl_FindExecutable (argv[0]); interp = Tcl_CreateInterp (); if (Tcl_Init (interp) != TCL_OK) { fprintf (stderr, "Tcl_Init error"); exit (-1); } if (Tk_Init (interp) != TCL_OK) { fprintf (stderr, "Tk_Init error"); exit (-1); } win = XtVaAppInitialize( &appContext, "mainWindow", NULL, 0, &argc, argv, NULL, 0 ); dis = XtDisplay (win); screen = DefaultScreen (dis); buttonShell = addXtBox ("mainPanel", win); testButton = XtVaCreateManagedWidget ( "Press Me", commandWidgetClass, buttonShell, NULL, 0 ); button = XtVaCreateManagedWidget ( "Exit", commandWidgetClass, buttonShell, NULL, 0 ); xtBox2 = addXtBox ("xtBox2", buttonShell); entry = XtVaCreateManagedWidget ( "entry", asciiTextWidgetClass, buttonShell, XtNtype, XawAsciiString, XtNlength, sizeof (entryBuffer), XtNeditType, XawtextEdit, NULL, 0 ) ; XtRealizeWidget (win); XtAddCallback (button, XtNcallback, Action, 0); XtAddCallback (testButton, XtNcallback, PressMe, 0); XtResizeWidget (win, 400, 400, 1); /*This MUST be here:*/ XSync (dis, 0); addTkToplevelToXtBox (".t", xtBox2); if (Tcl_EvalFile (interp, "test_script") != TCL_OK) { fprintf (stderr, "Tcl_EvalFile error %s", Tcl_GetStringResult (interp)); } makeXtBoxFitToplevel (xtBox2, ".t"); { fd_set readfds; int nfds; int tkFd = ConnectionNumber (Tk_Display (Tk_MainWindow (interp))); int xtFd = ConnectionNumber (XtDisplay (win)); nfds = (tkFd > xtFd) ? tkFd : xtFd; nfds++; for (;;) { FD_ZERO (&readfds); FD_SET (tkFd, &readfds); FD_SET (xtFd, &readfds); select (nfds, &readfds, NULL, NULL, (struct timeval *) NULL); while (XtAppPending (appContext) > 0) { XtAppNextEvent (appContext, &event); XtDispatchEvent (&event); } while (Tcl_DoOneEvent (TCL_DONT_WAIT)) ; } } return 0; }
The source code above invokes Tcl_EvalFile on test_script, which in this case looks like the code below:
proc main {} { wm withdraw . pack [button .t.b -text Hello -command {puts Hello}] pack [listbox .t.l] pack [button .t.b2 -text {Can you see me?} -command {.t.l insert end Yes}] -fill x .t.l insert end {John Doe} {Jane Doe} } main
Download a working example here (Linux users add -ldl to the Makefile): http://www.xmission.com/~georgeps/documentation/examples/TclTk_With_Others Note: You may need to change -ltcl83 and -ltk83 using a scheme like -ltcl8.3, depending on the name of your libtcl and libtk libraries.It looks like this:
You can solve the file handler problem using something like this:int data;Tcl_GetChannelHandle (Tcl_GetChannel (interp, Tcl_GetVar (interp, "inputSocket", NULL), NULL), TCL_READABLE, &data);Then add the data to the FD_SET but make sure that nfds is one greater than the largest file descriptor. See my Panache window manager if you need more of an example.
Of related interest is this [1] FAQ entry.