1818 lines
46 KiB
C
1818 lines
46 KiB
C
/*
|
||
* tkCmds.c --
|
||
*
|
||
* This file contains a collection of Tk-related Tcl commands
|
||
* that didn't fit in any particular file of the toolkit.
|
||
*
|
||
* Copyright (c) 1990-1994 The Regents of the University of California.
|
||
* Copyright (c) 1994-1996 Sun Microsystems, Inc.
|
||
*
|
||
* See the file "license.terms" for information on usage and redistribution
|
||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||
*
|
||
* SCCS: @(#) tkCmds.c 1.125 97/05/20 16:16:33
|
||
*/
|
||
|
||
#include "tkPort.h"
|
||
#include "tkInt.h"
|
||
#include <errno.h>
|
||
|
||
/*
|
||
* Forward declarations for procedures defined later in this file:
|
||
*/
|
||
|
||
static TkWindow * GetToplevel _ANSI_ARGS_((Tk_Window tkwin));
|
||
static char * WaitVariableProc _ANSI_ARGS_((ClientData clientData,
|
||
Tcl_Interp *interp, char *name1, char *name2,
|
||
int flags));
|
||
static void WaitVisibilityProc _ANSI_ARGS_((ClientData clientData,
|
||
XEvent *eventPtr));
|
||
static void WaitWindowProc _ANSI_ARGS_((ClientData clientData,
|
||
XEvent *eventPtr));
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_BellCmd --
|
||
*
|
||
* This procedure is invoked to process the "bell" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_BellCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window tkwin = (Tk_Window) clientData;
|
||
size_t length;
|
||
|
||
if ((argc != 1) && (argc != 3)) {
|
||
#ifdef STk_CODE
|
||
Tcl_AppendResult(interp, "wrong # args: should be (", argv[0],
|
||
" ?:displayof window?)", (char *) NULL);
|
||
#else
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||
" ?-displayof window?\"", (char *) NULL);
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
if (argc == 3) {
|
||
length = strlen(argv[1]);
|
||
if ((length < 2) || (strncmp(argv[1], "-displayof", length) != 0)) {
|
||
Tcl_AppendResult(interp, "bad option \"", argv[1],
|
||
#ifdef STk_CODE
|
||
"\": must be :displayof", (char *) NULL);
|
||
#else
|
||
"\": must be -displayof", (char *) NULL);
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
tkwin = Tk_NameToWindow(interp, argv[2], tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
XBell(Tk_Display(tkwin), 0);
|
||
XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
|
||
XFlush(Tk_Display(tkwin));
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_BindCmd --
|
||
*
|
||
* This procedure is invoked to process the "bind" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_BindCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window tkwin = (Tk_Window) clientData;
|
||
TkWindow *winPtr;
|
||
ClientData object;
|
||
|
||
if ((argc < 2) || (argc > 4)) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||
" window ?pattern? ?command?\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
if (argv[1][0] == '.') {
|
||
winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
|
||
if (winPtr == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
object = (ClientData) winPtr->pathName;
|
||
} else {
|
||
winPtr = (TkWindow *) clientData;
|
||
object = (ClientData) Tk_GetUid(argv[1]);
|
||
}
|
||
|
||
if (argc == 4) {
|
||
int append = 0;
|
||
unsigned long mask;
|
||
|
||
if (argv[3][0] == 0) {
|
||
return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,
|
||
object, argv[2]);
|
||
}
|
||
#ifndef STk_CODE
|
||
if (argv[3][0] == '+') {
|
||
argv[3]++;
|
||
append = 1;
|
||
}
|
||
#endif
|
||
mask = Tk_CreateBinding(interp, winPtr->mainPtr->bindingTable,
|
||
object, argv[2], argv[3], append);
|
||
if (mask == 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
} else if (argc == 3) {
|
||
char *command;
|
||
|
||
command = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable,
|
||
object, argv[2]);
|
||
if (command == NULL) {
|
||
Tcl_ResetResult(interp);
|
||
return TCL_OK;
|
||
}
|
||
|
||
#ifdef STk_CODE
|
||
if (*command == '(') {
|
||
char *p = interp->result;
|
||
|
||
/* Result is short (something like #pXXXX) => it fits in interp->result */
|
||
for (command++; *command && *command!=' ' && *command!=')'; command++)
|
||
*p++ = *command;
|
||
}
|
||
else
|
||
#endif
|
||
interp->result = command;
|
||
} else {
|
||
Tk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkBindEventProc --
|
||
*
|
||
* This procedure is invoked by Tk_HandleEvent for each event; it
|
||
* causes any appropriate bindings for that event to be invoked.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Depends on what bindings have been established with the "bind"
|
||
* command.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkBindEventProc(winPtr, eventPtr)
|
||
TkWindow *winPtr; /* Pointer to info about window. */
|
||
XEvent *eventPtr; /* Information about event. */
|
||
{
|
||
#define MAX_OBJS 20
|
||
ClientData objects[MAX_OBJS], *objPtr;
|
||
static Tk_Uid allUid = NULL;
|
||
TkWindow *topLevPtr;
|
||
int i, count;
|
||
char *p;
|
||
Tcl_HashEntry *hPtr;
|
||
|
||
if ((winPtr->mainPtr == NULL) || (winPtr->mainPtr->bindingTable == NULL)) {
|
||
return;
|
||
}
|
||
|
||
objPtr = objects;
|
||
if (winPtr->numTags != 0) {
|
||
/*
|
||
* Make a copy of the tags for the window, replacing window names
|
||
* with pointers to the pathName from the appropriate window.
|
||
*/
|
||
|
||
if (winPtr->numTags > MAX_OBJS) {
|
||
objPtr = (ClientData *) ckalloc((unsigned)
|
||
(winPtr->numTags * sizeof(ClientData)));
|
||
}
|
||
for (i = 0; i < winPtr->numTags; i++) {
|
||
p = (char *) winPtr->tagPtr[i];
|
||
if (*p == '.') {
|
||
hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);
|
||
if (hPtr != NULL) {
|
||
p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;
|
||
} else {
|
||
p = NULL;
|
||
}
|
||
}
|
||
objPtr[i] = (ClientData) p;
|
||
}
|
||
count = winPtr->numTags;
|
||
} else {
|
||
objPtr[0] = (ClientData) winPtr->pathName;
|
||
objPtr[1] = (ClientData) winPtr->classUid;
|
||
for (topLevPtr = winPtr;
|
||
(topLevPtr != NULL) && !(topLevPtr->flags & TK_TOP_LEVEL);
|
||
topLevPtr = topLevPtr->parentPtr) {
|
||
/* Empty loop body. */
|
||
}
|
||
if ((winPtr != topLevPtr) && (topLevPtr != NULL)) {
|
||
count = 4;
|
||
objPtr[2] = (ClientData) topLevPtr->pathName;
|
||
} else {
|
||
count = 3;
|
||
}
|
||
if (allUid == NULL) {
|
||
allUid = Tk_GetUid("all");
|
||
}
|
||
objPtr[count-1] = (ClientData) allUid;
|
||
}
|
||
Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,
|
||
count, objPtr);
|
||
if (objPtr != objects) {
|
||
ckfree((char *) objPtr);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_BindtagsCmd --
|
||
*
|
||
* This procedure is invoked to process the "bindtags" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_BindtagsCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window tkwin = (Tk_Window) clientData;
|
||
TkWindow *winPtr, *winPtr2;
|
||
int i, tagArgc;
|
||
char *p, **tagArgv;
|
||
|
||
if ((argc < 2) || (argc > 3)) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
||
" window ?tags?\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
|
||
if (winPtr == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (argc == 2) {
|
||
#ifdef STk_CODE
|
||
Tcl_AppendResult(interp, "(", NULL);
|
||
#endif
|
||
if (winPtr->numTags == 0) {
|
||
#ifdef STk_CODE
|
||
Tcl_AppendResult(interp, " #.", winPtr->pathName, NULL);
|
||
Tcl_AppendResult(interp, " \"", winPtr->classUid, "\"", NULL);
|
||
#else
|
||
Tcl_AppendElement(interp, winPtr->pathName);
|
||
Tcl_AppendElement(interp, winPtr->classUid);
|
||
#endif
|
||
for (winPtr2 = winPtr;
|
||
(winPtr2 != NULL) && !(winPtr2->flags & TK_TOP_LEVEL);
|
||
winPtr2 = winPtr2->parentPtr) {
|
||
/* Empty loop body. */
|
||
}
|
||
if ((winPtr != winPtr2) && (winPtr2 != NULL)) {
|
||
#ifdef STk_CODE
|
||
Tcl_AppendResult(interp, " #.", winPtr2->pathName, NULL);
|
||
#else
|
||
Tcl_AppendElement(interp, winPtr2->pathName);
|
||
#endif
|
||
}
|
||
#ifdef STk_CODE
|
||
Tcl_AppendElement(interp, "\"all\"");
|
||
#else
|
||
Tcl_AppendElement(interp, "all");
|
||
#endif
|
||
} else {
|
||
for (i = 0; i < winPtr->numTags; i++) {
|
||
#ifdef STk_CODE
|
||
char *s = (char *) winPtr->tagPtr[i];
|
||
|
||
if (*s == '.')
|
||
Tcl_AppendResult(interp, " #.", s, NULL);
|
||
else
|
||
Tcl_AppendResult(interp, " \"", s, "\"", NULL);
|
||
#else
|
||
Tcl_AppendElement(interp, (char *) winPtr->tagPtr[i]);
|
||
#endif
|
||
}
|
||
}
|
||
#ifdef STk_CODE
|
||
Tcl_AppendResult(interp, ")", NULL);
|
||
#endif
|
||
return TCL_OK;
|
||
}
|
||
if (winPtr->tagPtr != NULL) {
|
||
TkFreeBindingTags(winPtr);
|
||
}
|
||
if (argv[2][0] == 0) {
|
||
return TCL_OK;
|
||
}
|
||
if (Tcl_SplitList(interp, argv[2], &tagArgc, &tagArgv) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
winPtr->numTags = tagArgc;
|
||
winPtr->tagPtr = (ClientData *) ckalloc((unsigned)
|
||
(tagArgc * sizeof(ClientData)));
|
||
for (i = 0; i < tagArgc; i++) {
|
||
p = tagArgv[i];
|
||
if (p[0] == '.') {
|
||
char *copy;
|
||
|
||
/*
|
||
* Handle names starting with "." specially: store a malloc'ed
|
||
* string, rather than a Uid; at event time we'll look up the
|
||
* name in the window table and use the corresponding window,
|
||
* if there is one.
|
||
*/
|
||
|
||
copy = (char *) ckalloc((unsigned) (strlen(p) + 1));
|
||
strcpy(copy, p);
|
||
winPtr->tagPtr[i] = (ClientData) copy;
|
||
} else {
|
||
winPtr->tagPtr[i] = (ClientData) Tk_GetUid(p);
|
||
}
|
||
}
|
||
ckfree((char *) tagArgv);
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkFreeBindingTags --
|
||
*
|
||
* This procedure is called to free all of the binding tags
|
||
* associated with a window; typically it is only invoked where
|
||
* there are window-specific tags.
|
||
*
|
||
* Results:
|
||
* None.
|
||
*
|
||
* Side effects:
|
||
* Any binding tags for winPtr are freed.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
void
|
||
TkFreeBindingTags(winPtr)
|
||
TkWindow *winPtr; /* Window whose tags are to be released. */
|
||
{
|
||
int i;
|
||
char *p;
|
||
|
||
for (i = 0; i < winPtr->numTags; i++) {
|
||
p = (char *) (winPtr->tagPtr[i]);
|
||
if (*p == '.') {
|
||
/*
|
||
* Names starting with "." are malloced rather than Uids, so
|
||
* they have to be freed.
|
||
*/
|
||
|
||
ckfree(p);
|
||
}
|
||
}
|
||
ckfree((char *) winPtr->tagPtr);
|
||
winPtr->numTags = 0;
|
||
winPtr->tagPtr = NULL;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_DestroyCmd --
|
||
*
|
||
* This procedure is invoked to process the "destroy" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_DestroyCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window window;
|
||
Tk_Window tkwin = (Tk_Window) clientData;
|
||
int i;
|
||
|
||
for (i = 1; i < argc; i++) {
|
||
window = Tk_NameToWindow(interp, argv[i], tkwin);
|
||
if (window == NULL) {
|
||
Tcl_ResetResult(interp);
|
||
continue;
|
||
}
|
||
Tk_DestroyWindow(window);
|
||
if (window == tkwin) {
|
||
/*
|
||
* We just deleted the main window for the application! This
|
||
* makes it impossible to do anything more (tkwin isn't
|
||
* valid anymore).
|
||
*/
|
||
|
||
break;
|
||
}
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_LowerCmd --
|
||
*
|
||
* This procedure is invoked to process the "lower" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
int
|
||
Tk_LowerCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window mainwin = (Tk_Window) clientData;
|
||
Tk_Window tkwin, other;
|
||
|
||
if ((argc != 2) && (argc != 3)) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " window ?belowThis?\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
tkwin = Tk_NameToWindow(interp, argv[1], mainwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (argc == 2) {
|
||
other = NULL;
|
||
} else {
|
||
other = Tk_NameToWindow(interp, argv[2], mainwin);
|
||
if (other == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {
|
||
Tcl_AppendResult(interp, "can't lower \"", argv[1], "\" below \"",
|
||
argv[2], "\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_RaiseCmd --
|
||
*
|
||
* This procedure is invoked to process the "raise" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
int
|
||
Tk_RaiseCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window mainwin = (Tk_Window) clientData;
|
||
Tk_Window tkwin, other;
|
||
|
||
if ((argc != 2) && (argc != 3)) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " window ?aboveThis?\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
tkwin = Tk_NameToWindow(interp, argv[1], mainwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (argc == 2) {
|
||
other = NULL;
|
||
} else {
|
||
other = Tk_NameToWindow(interp, argv[2], mainwin);
|
||
if (other == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {
|
||
Tcl_AppendResult(interp, "can't raise \"", argv[1], "\" above \"",
|
||
argv[2], "\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_TkObjCmd --
|
||
*
|
||
* This procedure is invoked to process the "tk" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_TkObjCmd(clientData, interp, objc, objv)
|
||
ClientData clientData; /* Main window associated with interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int objc; /* Number of arguments. */
|
||
Tcl_Obj *CONST objv[]; /* Argument objects. */
|
||
{
|
||
int index;
|
||
Tk_Window tkwin;
|
||
static char *optionStrings[] = {
|
||
"appname", "scaling", NULL
|
||
};
|
||
enum options {
|
||
TK_APPNAME, TK_SCALING
|
||
};
|
||
|
||
tkwin = (Tk_Window) clientData;
|
||
|
||
if (objc < 2) {
|
||
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
|
||
return TCL_ERROR;
|
||
}
|
||
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
|
||
&index) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
switch ((enum options) index) {
|
||
case TK_APPNAME: {
|
||
TkWindow *winPtr;
|
||
char *string;
|
||
|
||
winPtr = (TkWindow *) tkwin;
|
||
|
||
if (objc > 3) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc == 3) {
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string));
|
||
}
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), winPtr->nameUid, -1);
|
||
break;
|
||
}
|
||
case TK_SCALING: {
|
||
Screen *screenPtr;
|
||
int skip, width, height;
|
||
double d;
|
||
|
||
screenPtr = Tk_Screen(tkwin);
|
||
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip == 2) {
|
||
d = 25.4 / 72;
|
||
d *= WidthOfScreen(screenPtr);
|
||
d /= WidthMMOfScreen(screenPtr);
|
||
Tcl_SetDoubleObj(Tcl_GetObjResult(interp), d);
|
||
} else if (objc - skip == 3) {
|
||
if (Tcl_GetDoubleFromObj(interp, objv[2 + skip], &d) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
d = (25.4 / 72) / d;
|
||
width = (int) (d * WidthOfScreen(screenPtr) + 0.5);
|
||
if (width <= 0) {
|
||
width = 1;
|
||
}
|
||
height = (int) (d * HeightOfScreen(screenPtr) + 0.5);
|
||
if (height <= 0) {
|
||
height = 1;
|
||
}
|
||
WidthMMOfScreen(screenPtr) = width;
|
||
HeightMMOfScreen(screenPtr) = height;
|
||
} else {
|
||
Tcl_WrongNumArgs(interp, 2, objv,
|
||
#ifdef STk_CODE
|
||
"?:displayof window? ?factor?");
|
||
#else
|
||
"?-displayof window? ?factor?");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_TkwaitCmd --
|
||
*
|
||
* This procedure is invoked to process the "tkwait" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
int
|
||
Tk_TkwaitCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tk_Window tkwin = (Tk_Window) clientData;
|
||
int c, done;
|
||
size_t length;
|
||
|
||
if (argc != 3) {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " variable|visibility|window name\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
c = argv[1][0];
|
||
length = strlen(argv[1]);
|
||
if ((c == 'v') && (strncmp(argv[1], "variable", length) == 0)
|
||
&& (length >= 2)) {
|
||
if (Tcl_TraceVar(interp, argv[2],
|
||
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||
WaitVariableProc, (ClientData) &done) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
done = 0;
|
||
while (!done) {
|
||
Tcl_DoOneEvent(0);
|
||
}
|
||
Tcl_UntraceVar(interp, argv[2],
|
||
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
||
WaitVariableProc, (ClientData) &done);
|
||
} else if ((c == 'v') && (strncmp(argv[1], "visibility", length) == 0)
|
||
&& (length >= 2)) {
|
||
Tk_Window window;
|
||
|
||
window = Tk_NameToWindow(interp, argv[2], tkwin);
|
||
if (window == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
Tk_CreateEventHandler(window, VisibilityChangeMask|StructureNotifyMask,
|
||
WaitVisibilityProc, (ClientData) &done);
|
||
done = 0;
|
||
while (!done) {
|
||
Tcl_DoOneEvent(0);
|
||
}
|
||
if (done != 1) {
|
||
/*
|
||
* Note that we do not delete the event handler because it
|
||
* was deleted automatically when the window was destroyed.
|
||
*/
|
||
|
||
Tcl_ResetResult(interp);
|
||
Tcl_AppendResult(interp, "window \"", argv[2],
|
||
"\" was deleted before its visibility changed",
|
||
(char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
Tk_DeleteEventHandler(window, VisibilityChangeMask|StructureNotifyMask,
|
||
WaitVisibilityProc, (ClientData) &done);
|
||
} else if ((c == 'w') && (strncmp(argv[1], "window", length) == 0)) {
|
||
Tk_Window window;
|
||
|
||
window = Tk_NameToWindow(interp, argv[2], tkwin);
|
||
if (window == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
Tk_CreateEventHandler(window, StructureNotifyMask,
|
||
WaitWindowProc, (ClientData) &done);
|
||
done = 0;
|
||
while (!done) {
|
||
Tcl_DoOneEvent(0);
|
||
}
|
||
/*
|
||
* Note: there's no need to delete the event handler. It was
|
||
* deleted automatically when the window was destroyed.
|
||
*/
|
||
} else {
|
||
Tcl_AppendResult(interp, "bad option \"", argv[1],
|
||
"\": must be variable, visibility, or window", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
/*
|
||
* Clear out the interpreter's result, since it may have been set
|
||
* by event handlers.
|
||
*/
|
||
|
||
Tcl_ResetResult(interp);
|
||
return TCL_OK;
|
||
}
|
||
|
||
/* ARGSUSED */
|
||
static char *
|
||
WaitVariableProc(clientData, interp, name1, name2, flags)
|
||
ClientData clientData; /* Pointer to integer to set to 1. */
|
||
Tcl_Interp *interp; /* Interpreter containing variable. */
|
||
char *name1; /* Name of variable. */
|
||
char *name2; /* Second part of variable name. */
|
||
int flags; /* Information about what happened. */
|
||
{
|
||
int *donePtr = (int *) clientData;
|
||
|
||
*donePtr = 1;
|
||
return (char *) NULL;
|
||
}
|
||
|
||
/*ARGSUSED*/
|
||
static void
|
||
WaitVisibilityProc(clientData, eventPtr)
|
||
ClientData clientData; /* Pointer to integer to set to 1. */
|
||
XEvent *eventPtr; /* Information about event (not used). */
|
||
{
|
||
int *donePtr = (int *) clientData;
|
||
|
||
if (eventPtr->type == VisibilityNotify) {
|
||
*donePtr = 1;
|
||
}
|
||
if (eventPtr->type == DestroyNotify) {
|
||
*donePtr = 2;
|
||
}
|
||
}
|
||
|
||
static void
|
||
WaitWindowProc(clientData, eventPtr)
|
||
ClientData clientData; /* Pointer to integer to set to 1. */
|
||
XEvent *eventPtr; /* Information about event. */
|
||
{
|
||
int *donePtr = (int *) clientData;
|
||
|
||
if (eventPtr->type == DestroyNotify) {
|
||
*donePtr = 1;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_UpdateCmd --
|
||
*
|
||
* This procedure is invoked to process the "update" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
int
|
||
Tk_UpdateCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
int flags;
|
||
TkDisplay *dispPtr;
|
||
|
||
if (argc == 1) {
|
||
flags = TCL_DONT_WAIT;
|
||
} else if (argc == 2) {
|
||
if (strncmp(argv[1], "idletasks", strlen(argv[1])) != 0) {
|
||
Tcl_AppendResult(interp, "bad option \"", argv[1],
|
||
"\": must be idletasks", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
flags = TCL_IDLE_EVENTS;
|
||
} else {
|
||
Tcl_AppendResult(interp, "wrong # args: should be \"",
|
||
argv[0], " ?idletasks?\"", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
/*
|
||
* Handle all pending events, sync all displays, and repeat over
|
||
* and over again until all pending events have been handled.
|
||
* Special note: it's possible that the entire application could
|
||
* be destroyed by an event handler that occurs during the update.
|
||
* Thus, don't use any information from tkwin after calling
|
||
* Tcl_DoOneEvent.
|
||
*/
|
||
|
||
while (1) {
|
||
while (Tcl_DoOneEvent(flags) != 0) {
|
||
/* Empty loop body */
|
||
}
|
||
for (dispPtr = tkDisplayList; dispPtr != NULL;
|
||
dispPtr = dispPtr->nextPtr) {
|
||
XSync(dispPtr->display, False);
|
||
}
|
||
if (Tcl_DoOneEvent(flags) == 0) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Must clear the interpreter's result because event handlers could
|
||
* have executed commands.
|
||
*/
|
||
|
||
Tcl_ResetResult(interp);
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* Tk_WinfoObjCmd --
|
||
*
|
||
* This procedure is invoked to process the "winfo" Tcl command.
|
||
* See the user documentation for details on what it does.
|
||
*
|
||
* Results:
|
||
* A standard Tcl result.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
Tk_WinfoObjCmd(clientData, interp, objc, objv)
|
||
ClientData clientData; /* Main window associated with
|
||
* interpreter. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int objc; /* Number of arguments. */
|
||
Tcl_Obj *CONST objv[]; /* Argument objects. */
|
||
{
|
||
int index, x, y, width, height, useX, useY, class, skip;
|
||
char buf[128];
|
||
char *string;
|
||
TkWindow *winPtr;
|
||
Tk_Window tkwin;
|
||
|
||
static TkStateMap visualMap[] = {
|
||
{PseudoColor, "pseudocolor"},
|
||
{GrayScale, "grayscale"},
|
||
{DirectColor, "directcolor"},
|
||
{TrueColor, "truecolor"},
|
||
{StaticColor, "staticcolor"},
|
||
{StaticGray, "staticgray"},
|
||
{-1, NULL}
|
||
};
|
||
static char *optionStrings[] = {
|
||
"cells", "children", "class", "colormapfull",
|
||
"depth", "geometry", "height", "id",
|
||
"ismapped", "manager", "name", "parent",
|
||
"pointerx", "pointery", "pointerxy", "reqheight",
|
||
"reqwidth", "rootx", "rooty", "screen",
|
||
"screencells", "screendepth", "screenheight", "screenwidth",
|
||
"screenmmheight","screenmmwidth","screenvisual","server",
|
||
"toplevel", "viewable", "visual", "visualid",
|
||
"vrootheight", "vrootwidth", "vrootx", "vrooty",
|
||
"width", "x", "y",
|
||
|
||
"atom", "atomname", "containing", "interps",
|
||
"pathname",
|
||
|
||
"exists", "fpixels", "pixels", "rgb",
|
||
"visualsavailable",
|
||
|
||
NULL
|
||
};
|
||
enum options {
|
||
WIN_CELLS, WIN_CHILDREN, WIN_CLASS, WIN_COLORMAPFULL,
|
||
WIN_DEPTH, WIN_GEOMETRY, WIN_HEIGHT, WIN_ID,
|
||
WIN_ISMAPPED, WIN_MANAGER, WIN_NAME, WIN_PARENT,
|
||
WIN_POINTERX, WIN_POINTERY, WIN_POINTERXY, WIN_REQHEIGHT,
|
||
WIN_REQWIDTH, WIN_ROOTX, WIN_ROOTY, WIN_SCREEN,
|
||
WIN_SCREENCELLS,WIN_SCREENDEPTH,WIN_SCREENHEIGHT,WIN_SCREENWIDTH,
|
||
WIN_SCREENMMHEIGHT,WIN_SCREENMMWIDTH,WIN_SCREENVISUAL,WIN_SERVER,
|
||
WIN_TOPLEVEL, WIN_VIEWABLE, WIN_VISUAL, WIN_VISUALID,
|
||
WIN_VROOTHEIGHT,WIN_VROOTWIDTH, WIN_VROOTX, WIN_VROOTY,
|
||
WIN_WIDTH, WIN_X, WIN_Y,
|
||
|
||
WIN_ATOM, WIN_ATOMNAME, WIN_CONTAINING, WIN_INTERPS,
|
||
WIN_PATHNAME,
|
||
|
||
WIN_EXISTS, WIN_FPIXELS, WIN_PIXELS, WIN_RGB,
|
||
WIN_VISUALSAVAILABLE
|
||
};
|
||
|
||
tkwin = (Tk_Window) clientData;
|
||
|
||
if (objc < 2) {
|
||
Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
|
||
return TCL_ERROR;
|
||
}
|
||
if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
|
||
&index) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
if (index < WIN_ATOM) {
|
||
if (objc != 3) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window");
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
tkwin = Tk_NameToWindow(interp, string, tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
}
|
||
winPtr = (TkWindow *) tkwin;
|
||
|
||
switch ((enum options) index) {
|
||
case WIN_CELLS: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
Tk_Visual(tkwin)->map_entries);
|
||
break;
|
||
}
|
||
case WIN_CHILDREN: {
|
||
Tcl_Obj *strPtr;
|
||
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp, STk_create_tcl_object(STk_get_NIL_value()));
|
||
winPtr = winPtr->childList;
|
||
for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
|
||
strPtr=STk_create_tcl_object(STk_get_widget_value(winPtr->pathName));
|
||
Tcl_ListObjAppendElement(NULL,
|
||
Tcl_GetObjResult(interp), strPtr);
|
||
}
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
winPtr = winPtr->childList;
|
||
for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
|
||
strPtr = Tcl_NewStringObj(winPtr->pathName, -1);
|
||
Tcl_ListObjAppendElement(NULL,
|
||
Tcl_GetObjResult(interp), strPtr);
|
||
}
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_CLASS: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_Class(tkwin), -1);
|
||
break;
|
||
}
|
||
case WIN_COLORMAPFULL: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
|
||
TkpCmapStressed(tkwin, Tk_Colormap(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_DEPTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Depth(tkwin));
|
||
break;
|
||
}
|
||
case WIN_GEOMETRY: {
|
||
Tcl_ResetResult(interp);
|
||
sprintf(buf, "%dx%d+%d+%d", Tk_Width(tkwin), Tk_Height(tkwin),
|
||
Tk_X(tkwin), Tk_Y(tkwin));
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
|
||
break;
|
||
}
|
||
case WIN_HEIGHT: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Height(tkwin));
|
||
break;
|
||
}
|
||
case WIN_ID: {
|
||
Tk_MakeWindowExist(tkwin);
|
||
TkpPrintWindowId(buf, Tk_WindowId(tkwin));
|
||
Tcl_ResetResult(interp);
|
||
#ifdef STk_CODE
|
||
{
|
||
long res;
|
||
sscanf(buf, "%lx", &res);
|
||
Tcl_SetLongObj(Tcl_GetObjResult(interp), res);
|
||
}
|
||
#else
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_ISMAPPED: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
|
||
(int) Tk_IsMapped(tkwin));
|
||
break;
|
||
}
|
||
case WIN_MANAGER: {
|
||
Tcl_ResetResult(interp);
|
||
if (winPtr->geomMgrPtr != NULL) {
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
winPtr->geomMgrPtr->name, -1);
|
||
}
|
||
#ifdef STk_CODE
|
||
else
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp), 0);
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_NAME: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), Tk_Name(tkwin), -1);
|
||
break;
|
||
}
|
||
case WIN_PARENT: {
|
||
Tcl_ResetResult(interp);
|
||
if (winPtr->parentPtr != NULL) {
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_get_widget_value(
|
||
winPtr->parentPtr->pathName)));
|
||
#else
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
winPtr->parentPtr->pathName, -1);
|
||
#endif
|
||
}
|
||
break;
|
||
}
|
||
case WIN_POINTERX: {
|
||
useX = 1;
|
||
useY = 0;
|
||
goto pointerxy;
|
||
}
|
||
case WIN_POINTERY: {
|
||
useX = 0;
|
||
useY = 1;
|
||
goto pointerxy;
|
||
}
|
||
case WIN_POINTERXY: {
|
||
useX = 1;
|
||
useY = 1;
|
||
|
||
pointerxy:
|
||
winPtr = GetToplevel(tkwin);
|
||
if (winPtr == NULL) {
|
||
x = -1;
|
||
y = -1;
|
||
} else {
|
||
TkGetPointerCoords((Tk_Window) winPtr, &x, &y);
|
||
}
|
||
Tcl_ResetResult(interp);
|
||
if (useX & useY) {
|
||
sprintf(buf, "%d %d", x, y);
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_convert_Tcl_string2list(buf)));
|
||
#else
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
|
||
#endif
|
||
} else if (useX) {
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
|
||
} else {
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
|
||
}
|
||
break;
|
||
}
|
||
case WIN_REQHEIGHT: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_ReqHeight(tkwin));
|
||
break;
|
||
}
|
||
case WIN_REQWIDTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_ReqWidth(tkwin));
|
||
break;
|
||
}
|
||
case WIN_ROOTX: {
|
||
Tk_GetRootCoords(tkwin, &x, &y);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
|
||
break;
|
||
}
|
||
case WIN_ROOTY: {
|
||
Tk_GetRootCoords(tkwin, &x, &y);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
|
||
break;
|
||
}
|
||
case WIN_SCREEN: {
|
||
sprintf(buf, "%d", Tk_ScreenNumber(tkwin));
|
||
Tcl_ResetResult(interp);
|
||
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
|
||
Tk_DisplayName(tkwin), ".", buf, NULL);
|
||
break;
|
||
}
|
||
case WIN_SCREENCELLS: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
CellsOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENDEPTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
DefaultDepthOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENHEIGHT: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
HeightOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENWIDTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
WidthOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENMMHEIGHT: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
HeightMMOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENMMWIDTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp),
|
||
WidthMMOfScreen(Tk_Screen(tkwin)));
|
||
break;
|
||
}
|
||
case WIN_SCREENVISUAL: {
|
||
class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class;
|
||
goto visual;
|
||
}
|
||
case WIN_SERVER: {
|
||
TkGetServerInfo(interp, tkwin);
|
||
break;
|
||
}
|
||
case WIN_TOPLEVEL: {
|
||
winPtr = GetToplevel(tkwin);
|
||
if (winPtr != NULL) {
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_get_widget_value(winPtr->pathName)));
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
winPtr->pathName, -1);
|
||
#endif
|
||
}
|
||
break;
|
||
}
|
||
case WIN_VIEWABLE: {
|
||
int viewable;
|
||
|
||
viewable = 0;
|
||
for ( ; ; winPtr = winPtr->parentPtr) {
|
||
if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {
|
||
break;
|
||
}
|
||
if (winPtr->flags & TK_TOP_LEVEL) {
|
||
viewable = 1;
|
||
break;
|
||
}
|
||
}
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp), viewable);
|
||
break;
|
||
}
|
||
case WIN_VISUAL: {
|
||
class = Tk_Visual(tkwin)->class;
|
||
|
||
visual:
|
||
string = TkFindStateString(visualMap, class);
|
||
if (string == NULL) {
|
||
string = "unknown";
|
||
}
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), string, -1);
|
||
break;
|
||
}
|
||
case WIN_VISUALID: {
|
||
#ifdef STk_CODE
|
||
Tcl_SetLongObj(Tcl_GetObjResult(interp),
|
||
(long) XVisualIDFromVisual(Tk_Visual(tkwin)));
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
sprintf(buf, "0x%x",
|
||
(unsigned int) XVisualIDFromVisual(Tk_Visual(tkwin)));
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_VROOTHEIGHT: {
|
||
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), height);
|
||
break;
|
||
}
|
||
case WIN_VROOTWIDTH: {
|
||
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), width);
|
||
break;
|
||
}
|
||
case WIN_VROOTX: {
|
||
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), x);
|
||
break;
|
||
}
|
||
case WIN_VROOTY: {
|
||
Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), y);
|
||
break;
|
||
}
|
||
case WIN_WIDTH: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Width(tkwin));
|
||
break;
|
||
}
|
||
case WIN_X: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_X(tkwin));
|
||
break;
|
||
}
|
||
case WIN_Y: {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), Tk_Y(tkwin));
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* Uses -displayof.
|
||
*/
|
||
|
||
case WIN_ATOM: {
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip != 3) {
|
||
#ifdef STk_CODE
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?:displayof window? name");
|
||
#else
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
objv += skip;
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetLongObj(Tcl_GetObjResult(interp),
|
||
(long) Tk_InternAtom(tkwin, string));
|
||
break;
|
||
}
|
||
case WIN_ATOMNAME: {
|
||
char *name;
|
||
long id;
|
||
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip != 3) {
|
||
#ifdef STk_CODE
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?:displayof window? id");
|
||
#else
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
objv += skip;
|
||
if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
Tcl_ResetResult(interp);
|
||
name = Tk_GetAtomName(tkwin, (Atom) id);
|
||
if (strcmp(name, "?bad atom?") == 0) {
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
|
||
"no atom exists with id \"", string, "\"", NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
|
||
break;
|
||
}
|
||
case WIN_CONTAINING: {
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip != 4) {
|
||
Tcl_WrongNumArgs(interp, 2, objv,
|
||
#ifdef STk_CODE
|
||
"?:displayof window? rootX rootY");
|
||
#else
|
||
"?-displayof window? rootX rootY");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
objv += skip;
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
if (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[3], NULL);
|
||
if (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
tkwin = Tk_CoordsToWindow(x, y, tkwin);
|
||
if (tkwin != NULL) {
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_get_widget_value(Tk_PathName(tkwin))));
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
Tk_PathName(tkwin), -1);
|
||
#endif
|
||
}
|
||
#ifdef STk_CODE
|
||
else {
|
||
/* No window; return #f */
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp),0);
|
||
}
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_INTERPS: {
|
||
int result;
|
||
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip != 2) {
|
||
#ifdef STk_CODE
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?:displayof window?");
|
||
#else
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
result = TkGetInterpNames(interp, tkwin);
|
||
#ifdef STk_CODE
|
||
if (result == TCL_OK) {
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_convert_Tcl_string2list(interp->result)));
|
||
}
|
||
#endif
|
||
return result;
|
||
}
|
||
case WIN_PATHNAME: {
|
||
int id;
|
||
|
||
skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
|
||
if (skip < 0) {
|
||
return TCL_ERROR;
|
||
}
|
||
if (objc - skip != 3) {
|
||
#ifdef STk_CODE
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?:displayof window? id");
|
||
#else
|
||
Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2 + skip], NULL);
|
||
if (TkpScanWindowId(interp, string, &id) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
winPtr = (TkWindow *)
|
||
Tk_IdToWindow(Tk_Display(tkwin), (Window) id);
|
||
if ((winPtr == NULL) ||
|
||
(winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
|
||
Tcl_ResetResult(interp);
|
||
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
|
||
"window id \"", string,
|
||
"\" doesn't exist in this application", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
/*
|
||
* If the window is a utility window with no associated path
|
||
* (such as a wrapper window or send communication window), just
|
||
* return an empty string.
|
||
*/
|
||
|
||
tkwin = (Tk_Window) winPtr;
|
||
if (Tk_PathName(tkwin) != NULL) {
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_get_widget_value(Tk_PathName(tkwin))));
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
Tk_PathName(tkwin), -1);
|
||
#endif
|
||
}
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* objv[3] is window.
|
||
*/
|
||
|
||
case WIN_EXISTS: {
|
||
int alive;
|
||
|
||
if (objc != 3) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window");
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
|
||
alive = 1;
|
||
if ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) {
|
||
alive = 0;
|
||
}
|
||
Tcl_ResetResult(interp); /* clear any error msg */
|
||
Tcl_SetBooleanObj(Tcl_GetObjResult(interp), alive);
|
||
break;
|
||
}
|
||
case WIN_FPIXELS: {
|
||
double mm, pixels;
|
||
|
||
if (objc != 4) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window number");
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
tkwin = Tk_NameToWindow(interp, string, tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[3], NULL);
|
||
if (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
pixels = mm * WidthOfScreen(Tk_Screen(tkwin))
|
||
/ WidthMMOfScreen(Tk_Screen(tkwin));
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetDoubleObj(Tcl_GetObjResult(interp), pixels);
|
||
break;
|
||
}
|
||
case WIN_PIXELS: {
|
||
int pixels;
|
||
|
||
if (objc != 4) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window number");
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
tkwin = Tk_NameToWindow(interp, string, tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[3], NULL);
|
||
if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {
|
||
return TCL_ERROR;
|
||
}
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetIntObj(Tcl_GetObjResult(interp), pixels);
|
||
break;
|
||
}
|
||
case WIN_RGB: {
|
||
XColor *colorPtr;
|
||
|
||
if (objc != 4) {
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window colorName");
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
tkwin = Tk_NameToWindow(interp, string, tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[3], NULL);
|
||
colorPtr = Tk_GetColor(interp, tkwin, string);
|
||
if (colorPtr == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
sprintf(buf, "%d %d %d", colorPtr->red, colorPtr->green,
|
||
colorPtr->blue);
|
||
Tk_FreeColor(colorPtr);
|
||
#ifdef STk_CODE
|
||
Tcl_SetObjResult(interp,
|
||
STk_create_tcl_object(
|
||
STk_convert_Tcl_string2list(buf)));
|
||
#else
|
||
Tcl_ResetResult(interp);
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, -1);
|
||
#endif
|
||
break;
|
||
}
|
||
case WIN_VISUALSAVAILABLE: {
|
||
XVisualInfo template, *visInfoPtr;
|
||
int count, i;
|
||
char visualIdString[16];
|
||
int includeVisualId;
|
||
#ifndef STk_CODE
|
||
Tcl_Obj *strPtr;
|
||
#endif
|
||
|
||
if (objc == 3) {
|
||
includeVisualId = 0;
|
||
} else if ((objc == 4)
|
||
&& (strcmp(Tcl_GetStringFromObj(objv[3], NULL),
|
||
"includeids") == 0)) {
|
||
includeVisualId = 1;
|
||
} else {
|
||
#ifdef STk_CODE
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window ?'includeids?");
|
||
#else
|
||
Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?");
|
||
#endif
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
string = Tcl_GetStringFromObj(objv[2], NULL);
|
||
tkwin = Tk_NameToWindow(interp, string, tkwin);
|
||
if (tkwin == NULL) {
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
template.screen = Tk_ScreenNumber(tkwin);
|
||
visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,
|
||
&template, &count);
|
||
Tcl_ResetResult(interp);
|
||
if (visInfoPtr == NULL) {
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
"can't find any visuals for screen", -1);
|
||
return TCL_ERROR;
|
||
}
|
||
for (i = 0; i < count; i++) {
|
||
string = TkFindStateString(visualMap, visInfoPtr[i].class);
|
||
if (string == NULL) {
|
||
strcpy(buf, "unknown");
|
||
} else {
|
||
sprintf(buf, "%s %d", string, visInfoPtr[i].depth);
|
||
}
|
||
if (includeVisualId) {
|
||
#ifdef STk_CODE
|
||
sprintf(visualIdString, " %d",
|
||
#else
|
||
sprintf(visualIdString, " 0x%x",
|
||
#endif
|
||
(unsigned int) visInfoPtr[i].visualid);
|
||
strcat(buf, visualIdString);
|
||
}
|
||
#ifdef STk_CODE
|
||
Tcl_ListObjAppendElement(interp,
|
||
Tcl_GetObjResult(interp),
|
||
STk_convert_Tcl_string2list(buf));
|
||
#else
|
||
strPtr = Tcl_NewStringObj(buf, -1);
|
||
Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp),
|
||
strPtr);
|
||
#endif
|
||
}
|
||
XFree((char *) visInfoPtr);
|
||
break;
|
||
}
|
||
}
|
||
return TCL_OK;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkGetDisplayOf --
|
||
*
|
||
* Parses a "-displayof window" option for various commands. If
|
||
* present, the literal "-displayof" should be in objv[0] and the
|
||
* window name in objv[1].
|
||
*
|
||
* Results:
|
||
* The return value is 0 if the argument strings did not contain
|
||
* the "-displayof" option. The return value is 2 if the
|
||
* argument strings contained both the "-displayof" option and
|
||
* a valid window name. Otherwise, the return value is -1 if
|
||
* the window name was missing or did not specify a valid window.
|
||
*
|
||
* If the return value was 2, *tkwinPtr is filled with the
|
||
* token for the window specified on the command line. If the
|
||
* return value was -1, an error message is left in interp's
|
||
* result object.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
int
|
||
TkGetDisplayOf(interp, objc, objv, tkwinPtr)
|
||
Tcl_Interp *interp; /* Interpreter for error reporting. */
|
||
int objc; /* Number of arguments. */
|
||
Tcl_Obj *CONST objv[]; /* Argument objects. If it is present,
|
||
* "-displayof" should be in objv[0] and
|
||
* objv[1] the name of a window. */
|
||
Tk_Window *tkwinPtr; /* On input, contains main window of
|
||
* application associated with interp. On
|
||
* output, filled with window specified as
|
||
* option to "-displayof" argument, or
|
||
* unmodified if "-displayof" argument was not
|
||
* present. */
|
||
{
|
||
char *string;
|
||
int length;
|
||
|
||
if (objc < 1) {
|
||
return 0;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[0], &length);
|
||
if ((length >= 2) && (strncmp(string, "-displayof", (unsigned) length) == 0)) {
|
||
if (objc < 2) {
|
||
Tcl_SetStringObj(Tcl_GetObjResult(interp),
|
||
#ifdef STk_CODE
|
||
"value for \":displayof\" missing", -1);
|
||
#else
|
||
"value for \"-displayof\" missing", -1);
|
||
#endif
|
||
return -1;
|
||
}
|
||
string = Tcl_GetStringFromObj(objv[1], NULL);
|
||
*tkwinPtr = Tk_NameToWindow(interp, string, *tkwinPtr);
|
||
if (*tkwinPtr == NULL) {
|
||
return -1;
|
||
}
|
||
return 2;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* TkDeadAppCmd --
|
||
*
|
||
* If an application has been deleted then all Tk commands will be
|
||
* re-bound to this procedure.
|
||
*
|
||
* Results:
|
||
* A standard Tcl error is reported to let the user know that
|
||
* the application is dead.
|
||
*
|
||
* Side effects:
|
||
* See the user documentation.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
/* ARGSUSED */
|
||
int
|
||
TkDeadAppCmd(clientData, interp, argc, argv)
|
||
ClientData clientData; /* Dummy. */
|
||
Tcl_Interp *interp; /* Current interpreter. */
|
||
int argc; /* Number of arguments. */
|
||
char **argv; /* Argument strings. */
|
||
{
|
||
Tcl_AppendResult(interp, "can't invoke \"", argv[0],
|
||
"\" command: application has been destroyed", (char *) NULL);
|
||
return TCL_ERROR;
|
||
}
|
||
|
||
/*
|
||
*----------------------------------------------------------------------
|
||
*
|
||
* GetToplevel --
|
||
*
|
||
* Retrieves the toplevel window which is the nearest ancestor of
|
||
* of the specified window.
|
||
*
|
||
* Results:
|
||
* Returns the toplevel window or NULL if the window has no
|
||
* ancestor which is a toplevel.
|
||
*
|
||
* Side effects:
|
||
* None.
|
||
*
|
||
*----------------------------------------------------------------------
|
||
*/
|
||
|
||
static TkWindow *
|
||
GetToplevel(tkwin)
|
||
Tk_Window tkwin; /* Window for which the toplevel should be
|
||
* deterined. */
|
||
{
|
||
TkWindow *winPtr = (TkWindow *) tkwin;
|
||
|
||
while (!(winPtr->flags & TK_TOP_LEVEL)) {
|
||
winPtr = winPtr->parentPtr;
|
||
if (winPtr == NULL) {
|
||
return NULL;
|
||
}
|
||
}
|
||
return winPtr;
|
||
}
|