Esempio n. 1
0
/* RaiseLabelWidget --
 * 	Raise the -labelwidget to ensure that the labelframe doesn't
 * 	obscure it (if it's not a direct child), or bring it to
 * 	the top of the stacking order (if it is).
 */
static void RaiseLabelWidget(Labelframe *lframe)
{
    Tk_Window parent = Tk_Parent(lframe->label.labelWidget);
    Tk_Window sibling = NULL;
    Tk_Window w = lframe->core.tkwin;

    while (w && w != parent) {
	sibling = w;
	w = Tk_Parent(w);
    }

    Tk_RestackWindow(lframe->label.labelWidget, Above, sibling);
}
Esempio n. 2
0
/*
 *---------------------------------------------------------------------------
 *
 * Blt_GetToplevelWindow --
 *
 *      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.
 *
 *---------------------------------------------------------------------------
 */
Tk_Window
Blt_GetToplevelWindow(Tk_Window tkwin) /* Window for which the toplevel
					* should be deterined. */
{
     while (!Tk_IsTopLevel(tkwin)) {
         tkwin = Tk_Parent(tkwin);
	 if (tkwin == NULL) {
             return NULL;
         }
     }
     return tkwin;
}
Esempio n. 3
0
File: tkImage.c Progetto: tcltk/tk
/*ARGSUSED*/
void
Tk_SetTSOrigin(
    Tk_Window tkwin,
    GC gc,
    int x, int y)
{
    while (!Tk_TopWinHierarchy(tkwin)) {
	x -= Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
	y -= Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
	tkwin = Tk_Parent(tkwin);
    }
    XSetTSOrigin(Tk_Display(tkwin), gc, x, y);
}
Esempio n. 4
0
static void
EmbWinDelayedUnmap(
    ClientData clientData)	/* Token for the window to be unmapped. */
{
    TkTextEmbWindowClient *client = clientData;

    if (!client->displayed && (client->tkwin != NULL)) {
	if (client->textPtr->tkwin != Tk_Parent(client->tkwin)) {
	    Tk_UnmaintainGeometry(client->tkwin, client->textPtr->tkwin);
	} else {
	    Tk_UnmapWindow(client->tkwin);
	}
    }
}
Esempio n. 5
0
/*
 * A managed window turns control over
 * to another geometry manager.
 */
static void
WindowItemLostSlave(ClientData  client_data,
                    Tk_Window   win)
{
  WindowItem wind = (WindowItem) client_data;
  ZnWInfo *wi = ((ZnItem) wind)->wi;
  
  Tk_DeleteEventHandler(wi->win, StructureNotifyMask, WindowDeleted,
                        (ClientData) wind);
  if (wi->win != Tk_Parent(wind->win)) {
    Tk_UnmaintainGeometry(wind->win, wi->win);
  }
  Tk_UnmapWindow(wind->win);
  wind->win = NULL;
}
Esempio n. 6
0
/* ++ Ttk_Maintainable(interp, slave, master) --
 * 	Utility routine.  Verifies that 'master' may be used to maintain
 *	the geometry of 'slave' via Tk_MaintainGeometry:
 *
 * 	+ 'master' is either 'slave's parent -OR-
 * 	+ 'master is a descendant of 'slave's parent.
 * 	+ 'slave' is not a toplevel window
 * 	+ 'slave' belongs to the same toplevel as 'master'
 *
 * Returns: 1 if OK; otherwise 0, leaving an error message in 'interp'.
 */
int Ttk_Maintainable(Tcl_Interp *interp, Tk_Window slave, Tk_Window master)
{
    Tk_Window ancestor = master, parent = Tk_Parent(slave);

    if (Tk_IsTopLevel(slave) || slave == master) {
	goto badWindow;
    }

    while (ancestor != parent) {
	if (Tk_IsTopLevel(ancestor)) {
	    goto badWindow;
	}
	ancestor = Tk_Parent(ancestor);
    }

    return 1;

badWindow:
    Tcl_AppendResult(interp,
	"can't add ", Tk_PathName(slave),
	" as slave of ", Tk_PathName(master),
	NULL);
    return 0;
}
Esempio n. 7
0
static void
EmbWinLostSlaveProc(
    ClientData clientData,	/* Pointer to record describing window item. */
    Tk_Window tkwin)		/* Window that was claimed away by another
				 * geometry manager. */
{
    TkTextEmbWindowClient *client = clientData;
    TkTextSegment *ewPtr = client->parent;
    TkTextIndex index;
    Tcl_HashEntry *hPtr;
    TkTextEmbWindowClient *loop;

    Tk_DeleteEventHandler(client->tkwin, StructureNotifyMask,
	    EmbWinStructureProc, client);
    Tcl_CancelIdleCall(EmbWinDelayedUnmap, client);
    if (client->textPtr->tkwin != Tk_Parent(tkwin)) {
	Tk_UnmaintainGeometry(tkwin, client->textPtr->tkwin);
    } else {
	Tk_UnmapWindow(tkwin);
    }
    hPtr = Tcl_FindHashEntry(&ewPtr->body.ew.sharedTextPtr->windowTable,
	    Tk_PathName(client->tkwin));
    Tcl_DeleteHashEntry(hPtr);
    client->tkwin = NULL;
    ewPtr->body.ew.tkwin = NULL;

    /*
     * Free up the memory allocation for this client.
     */

    loop = ewPtr->body.ew.clients;
    if (loop == client) {
	ewPtr->body.ew.clients = client->next;
    } else {
	while (loop->next != client) {
	    loop = loop->next;
	}
	loop->next = client->next;
    }
    ckfree((char *) client);

    index.tree = ewPtr->body.ew.sharedTextPtr->tree;
    index.linePtr = ewPtr->body.ew.linePtr;
    index.byteIndex = TkTextSegToOffset(ewPtr, ewPtr->body.ew.linePtr);
    TkTextChanged(ewPtr->body.ew.sharedTextPtr, NULL, &index, &index);
    TkTextInvalidateLineMetrics(ewPtr->body.ew.sharedTextPtr, NULL,
	    index.linePtr, 0, TK_TEXT_INVALIDATE_ONLY);
}
Esempio n. 8
0
	/* ARGSUSED */
static void
WinItemLostSlaveProc(
    ClientData clientData,	/* WindowItem structure for slave window that
				 * was stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
{
    WindowItem *winItemPtr = clientData;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);

    Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
	    WinItemStructureProc, winItemPtr);
    if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
	Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
    }
    Tk_UnmapWindow(winItemPtr->tkwin);
    winItemPtr->tkwin = NULL;
}
Esempio n. 9
0
static void
DeleteWinItem(
    Tk_Canvas canvas,		/* Overall info about widget. */
    Tk_Item *itemPtr,		/* Item that is being deleted. */
    Display *display)		/* Display containing window for canvas. */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);

    if (winItemPtr->tkwin != NULL) {
	Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
		WinItemStructureProc, winItemPtr);
	Tk_ManageGeometry(winItemPtr->tkwin, NULL, NULL);
	if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
	Tk_UnmapWindow(winItemPtr->tkwin);
    }
}
Esempio n. 10
0
	/* ARGSUSED */
static void
PlaceLostSlaveProc(
    ClientData clientData,	/* Slave structure for slave window that was
				 * stolen away. */
    Tk_Window tkwin)		/* Tk's handle for the slave window. */
{
    register Slave *slavePtr = clientData;
    TkDisplay *dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr;

    if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) {
	Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
    }
    Tk_UnmapWindow(tkwin);
    UnlinkSlave(slavePtr);
    Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
	    (char *) tkwin));
    Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
	    slavePtr);
    FreeSlave(slavePtr);
}
Esempio n. 11
0
	/*ARGSUSED*/
static int
EmbWinLayoutProc(
    TkText *textPtr,		/* Text widget being layed out. */
    TkTextIndex *indexPtr,	/* Identifies first character in chunk. */
    TkTextSegment *ewPtr,	/* Segment corresponding to indexPtr. */
    int offset,			/* Offset within segPtr corresponding to
				 * indexPtr (always 0). */
    int maxX,			/* Chunk must not occupy pixels at this
				 * position or higher. */
    int maxChars,		/* Chunk must not include more than this many
				 * characters. */
    int noCharsYet,		/* Non-zero means no characters have been
				 * assigned to this line yet. */
    TkWrapMode wrapMode,	/* Wrap mode to use for line:
				 * TEXT_WRAPMODE_CHAR, TEXT_WRAPMODE_NONE, or
				 * TEXT_WRAPMODE_WORD. */
    register TkTextDispChunk *chunkPtr)
				/* Structure to fill in with information about
				 * this chunk. The x field has already been
				 * set by the caller. */
{
    int width, height;
    TkTextEmbWindowClient *client;

    if (offset != 0) {
	Tcl_Panic("Non-zero offset in EmbWinLayoutProc");
    }

    client = EmbWinGetClient(textPtr, ewPtr);
    if (client == NULL) {
	ewPtr->body.ew.tkwin = NULL;
    } else {
	ewPtr->body.ew.tkwin = client->tkwin;
    }

    if ((ewPtr->body.ew.tkwin == NULL) && (ewPtr->body.ew.create != NULL)) {
	int code, isNew;
	Tk_Window ancestor;
	Tcl_HashEntry *hPtr;
	const char *before, *string;
	Tcl_DString name, buf, *dsPtr = NULL;

	before = ewPtr->body.ew.create;

	/*
	 * Find everything up to the next % character and append it to the
	 * result string.
	 */

	string = before;
	while (*string != 0) {
	    if ((*string == '%') && (string[1] == '%' || string[1] == 'W')) {
		if (dsPtr == NULL) {
		    Tcl_DStringInit(&buf);
		    dsPtr = &buf;
		}
		if (string != before) {
		    Tcl_DStringAppend(dsPtr, before, (int) (string-before));
		    before = string;
		}
		if (string[1] == '%') {
		    Tcl_DStringAppend(dsPtr, "%", 1);
		} else {
		    /*
		     * Substitute string as proper Tcl list element.
		     */

		    int spaceNeeded, cvtFlags, length;
		    const char *str = Tk_PathName(textPtr->tkwin);

		    spaceNeeded = Tcl_ScanElement(str, &cvtFlags);
		    length = Tcl_DStringLength(dsPtr);
		    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
		    spaceNeeded = Tcl_ConvertElement(str,
			    Tcl_DStringValue(dsPtr) + length,
			    cvtFlags | TCL_DONT_USE_BRACES);
		    Tcl_DStringSetLength(dsPtr, length + spaceNeeded);
		}
		before += 2;
		string++;
	    }
	    string++;
	}

	/*
	 * The window doesn't currently exist. Create it by evaluating the
	 * creation script. The script must return the window's path name:
	 * look up that name to get back to the window token. Then register
	 * ourselves as the geometry manager for the window.
	 */

	if (dsPtr != NULL) {
	    Tcl_DStringAppend(dsPtr, before, (int) (string-before));
	    code = Tcl_GlobalEval(textPtr->interp, Tcl_DStringValue(dsPtr));
	    Tcl_DStringFree(dsPtr);
	} else {
	    code = Tcl_GlobalEval(textPtr->interp, ewPtr->body.ew.create);
	}
	if (code != TCL_OK) {
	createError:
	    Tcl_BackgroundException(textPtr->interp, code);
	    goto gotWindow;
	}
	Tcl_DStringInit(&name);
	Tcl_DStringAppend(&name, Tcl_GetStringResult(textPtr->interp), -1);
	Tcl_ResetResult(textPtr->interp);
	ewPtr->body.ew.tkwin = Tk_NameToWindow(textPtr->interp,
		Tcl_DStringValue(&name), textPtr->tkwin);
	Tcl_DStringFree(&name);
	if (ewPtr->body.ew.tkwin == NULL) {
	    goto createError;
	}
	for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == Tk_Parent(ewPtr->body.ew.tkwin)) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
	    badMaster:
		Tcl_AppendResult(textPtr->interp, "can't embed ",
			Tk_PathName(ewPtr->body.ew.tkwin), " relative to ",
			Tk_PathName(textPtr->tkwin), NULL);
		Tcl_BackgroundError(textPtr->interp);
		ewPtr->body.ew.tkwin = NULL;
		goto gotWindow;
	    }
	}
	if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
		|| (textPtr->tkwin == ewPtr->body.ew.tkwin)) {
	    goto badMaster;
	}

	if (client == NULL) {
	    /*
	     * We just used a '-create' script to make a new window, which we
	     * now need to add to our client list.
	     */

	    client = (TkTextEmbWindowClient *)
		    ckalloc(sizeof(TkTextEmbWindowClient));
	    client->next = ewPtr->body.ew.clients;
	    client->textPtr = textPtr;
	    client->tkwin = NULL;
	    client->chunkCount = 0;
	    client->displayed = 0;
	    client->parent = ewPtr;
	    ewPtr->body.ew.clients = client;
	}

	client->tkwin = ewPtr->body.ew.tkwin;
	Tk_ManageGeometry(client->tkwin, &textGeomType, client);
	Tk_CreateEventHandler(client->tkwin, StructureNotifyMask,
		EmbWinStructureProc, client);

	/*
	 * Special trick! Must enter into the hash table *after* calling
	 * Tk_ManageGeometry: if the window was already managed elsewhere in
	 * this text, the Tk_ManageGeometry call will cause the entry to be
	 * removed, which could potentially lose the new entry.
	 */

	hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
		Tk_PathName(client->tkwin), &isNew);
	Tcl_SetHashValue(hPtr, ewPtr);
    }

    /*
     * See if there's room for this window on this line.
     */

  gotWindow:
    if (ewPtr->body.ew.tkwin == NULL) {
	width = 0;
	height = 0;
    } else {
	width = Tk_ReqWidth(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padX;
	height = Tk_ReqHeight(ewPtr->body.ew.tkwin) + 2*ewPtr->body.ew.padY;
    }
    if ((width > (maxX - chunkPtr->x))
	    && !noCharsYet && (textPtr->wrapMode != TEXT_WRAPMODE_NONE)) {
	return 0;
    }

    /*
     * Fill in the chunk structure.
     */

    chunkPtr->displayProc = TkTextEmbWinDisplayProc;
    chunkPtr->undisplayProc = EmbWinUndisplayProc;
    chunkPtr->measureProc = NULL;
    chunkPtr->bboxProc = EmbWinBboxProc;
    chunkPtr->numBytes = 1;
    if (ewPtr->body.ew.align == ALIGN_BASELINE) {
	chunkPtr->minAscent = height - ewPtr->body.ew.padY;
	chunkPtr->minDescent = ewPtr->body.ew.padY;
	chunkPtr->minHeight = 0;
    } else {
	chunkPtr->minAscent = 0;
	chunkPtr->minDescent = 0;
	chunkPtr->minHeight = height;
    }
    chunkPtr->width = width;
    chunkPtr->breakIndex = -1;
    chunkPtr->breakIndex = 1;
    chunkPtr->clientData = ewPtr;
    if (client != NULL) {
	client->chunkCount += 1;
    }
    return 1;
}
Esempio n. 12
0
File: tkBusy.c Progetto: das/tk
static void
RefWinEventProc(
    ClientData clientData,	/* Busy window record */
    register XEvent *eventPtr)	/* Event which triggered call to routine */
{
    register Busy *busyPtr = clientData;

    switch (eventPtr->type) {
    case ReparentNotify:
    case DestroyNotify:
        /*
         * Arrange for the busy structure to be removed at a proper time.
         */

        Tcl_EventuallyFree(busyPtr, DestroyBusy);
        break;

    case ConfigureNotify:
        if ((busyPtr->width != Tk_Width(busyPtr->tkRef)) ||
                (busyPtr->height != Tk_Height(busyPtr->tkRef)) ||
                (busyPtr->x != Tk_X(busyPtr->tkRef)) ||
                (busyPtr->y != Tk_Y(busyPtr->tkRef))) {
            int x, y;

            busyPtr->width = Tk_Width(busyPtr->tkRef);
            busyPtr->height = Tk_Height(busyPtr->tkRef);
            busyPtr->x = Tk_X(busyPtr->tkRef);
            busyPtr->y = Tk_Y(busyPtr->tkRef);

            x = y = 0;

            if (busyPtr->tkParent != busyPtr->tkRef) {
                Tk_Window tkwin;

                for (tkwin = busyPtr->tkRef; (tkwin != NULL) &&
                        (!Tk_IsTopLevel(tkwin)); tkwin = Tk_Parent(tkwin)) {
                    if (tkwin == busyPtr->tkParent) {
                        break;
                    }
                    x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
                    y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
                }
            }
            if (busyPtr->tkBusy != NULL) {
                Tk_MoveResizeWindow(busyPtr->tkBusy, x, y, busyPtr->width,
                                    busyPtr->height);
                TkpShowBusyWindow(busyPtr);
            }
        }
        break;

    case MapNotify:
        if (busyPtr->tkParent != busyPtr->tkRef) {
            TkpShowBusyWindow(busyPtr);
        }
        break;

    case UnmapNotify:
        if (busyPtr->tkParent != busyPtr->tkRef) {
            TkpHideBusyWindow(busyPtr);
        }
        break;
    }
}
Esempio n. 13
0
File: tkBusy.c Progetto: das/tk
static Busy *
CreateBusy(
    Tcl_Interp *interp,		/* Interpreter to report error to */
    Tk_Window tkRef)		/* Window hosting the busy window */
{
    Busy *busyPtr;
    int length, x, y;
    const char *fmt;
    char *name;
    Tk_Window tkBusy, tkChild, tkParent;
    Window parent;
    Tk_FakeWin *winPtr;

    busyPtr = (Busy *) ckalloc(sizeof(Busy));
    x = y = 0;
    length = strlen(Tk_Name(tkRef));
    name = ckalloc(length + 6);
    if (Tk_IsTopLevel(tkRef)) {
        fmt = "_Busy";		/* Child */
        tkParent = tkRef;
    } else {
        Tk_Window tkwin;

        fmt = "%s_Busy";	/* Sibling */
        tkParent = Tk_Parent(tkRef);
        for (tkwin = tkRef; (tkwin != NULL) && !Tk_IsTopLevel(tkwin);
                tkwin = Tk_Parent(tkwin)) {
            if (tkwin == tkParent) {
                break;
            }
            x += Tk_X(tkwin) + Tk_Changes(tkwin)->border_width;
            y += Tk_Y(tkwin) + Tk_Changes(tkwin)->border_width;
        }
    }
    for (tkChild = FirstChild(tkParent); tkChild != NULL;
            tkChild = NextChild(tkChild)) {
        Tk_MakeWindowExist(tkChild);
    }
    sprintf(name, fmt, Tk_Name(tkRef));
    tkBusy = Tk_CreateWindow(interp, tkParent, name, NULL);
    ckfree(name);

    if (tkBusy == NULL) {
        return NULL;
    }
    Tk_MakeWindowExist(tkRef);
    busyPtr->display = Tk_Display(tkRef);
    busyPtr->interp = interp;
    busyPtr->tkRef = tkRef;
    busyPtr->tkParent = tkParent;
    busyPtr->tkBusy = tkBusy;
    busyPtr->width = Tk_Width(tkRef);
    busyPtr->height = Tk_Height(tkRef);
    busyPtr->x = Tk_X(tkRef);
    busyPtr->y = Tk_Y(tkRef);
    busyPtr->cursor = None;
    Tk_SetClass(tkBusy, "Busy");
    busyPtr->optionTable = Tk_CreateOptionTable(interp, busyOptionSpecs);
    if (Tk_InitOptions(interp, (char *) busyPtr, busyPtr->optionTable,
                       tkBusy) != TCL_OK) {
        Tk_DestroyWindow(tkBusy);
        return NULL;
    }
    SetWindowInstanceData(tkBusy, busyPtr);
    winPtr = (Tk_FakeWin *) tkRef;

    TkpCreateBusy(winPtr, tkRef, &parent, tkParent, busyPtr);

    MakeTransparentWindowExist(tkBusy, parent);

    Tk_MoveResizeWindow(tkBusy, x, y, busyPtr->width, busyPtr->height);

    /*
     * Only worry if the busy window is destroyed.
     */

    Tk_CreateEventHandler(tkBusy, StructureNotifyMask, BusyEventProc,
                          busyPtr);

    /*
     * Indicate that the busy window's geometry is being managed. This will
     * also notify us if the busy window is ever packed.
     */

    Tk_ManageGeometry(tkBusy, &busyMgrInfo, busyPtr);
    if (busyPtr->cursor != None) {
        Tk_DefineCursor(tkBusy, busyPtr->cursor);
    }

    /*
     * Track the reference window to see if it is resized or destroyed.
     */

    Tk_CreateEventHandler(tkRef, StructureNotifyMask, RefWinEventProc,
                          busyPtr);
    return busyPtr;
}
Esempio n. 14
0
static int
EmbWinConfigure(
    TkText *textPtr,		/* Information about text widget that contains
				 * embedded window. */
    TkTextSegment *ewPtr,	/* Embedded window to be configured. */
    int objc,			/* Number of strings in objv. */
    Tcl_Obj *const objv[])	/* Array of objects describing configuration
				 * options. */
{
    Tk_Window oldWindow;
    TkTextEmbWindowClient *client;

    /*
     * Copy over client specific value before querying or setting.
     */

    client = EmbWinGetClient(textPtr, ewPtr);
    if (client != NULL) {
	ewPtr->body.ew.tkwin = client->tkwin;
    } else {
	ewPtr->body.ew.tkwin = NULL;
    }

    oldWindow = ewPtr->body.ew.tkwin;
    if (Tk_SetOptions(textPtr->interp, (char *) &ewPtr->body.ew,
	    ewPtr->body.ew.optionTable, objc, objv, textPtr->tkwin, NULL,
	    NULL) != TCL_OK) {
	return TCL_ERROR;
    }

    if (oldWindow != ewPtr->body.ew.tkwin) {
	if (oldWindow != NULL) {
	    Tcl_DeleteHashEntry(Tcl_FindHashEntry(
		    &textPtr->sharedTextPtr->windowTable,
		    Tk_PathName(oldWindow)));
	    Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
		    EmbWinStructureProc, client);
	    Tk_ManageGeometry(oldWindow, NULL, NULL);
	    if (textPtr->tkwin != Tk_Parent(oldWindow)) {
		Tk_UnmaintainGeometry(oldWindow, textPtr->tkwin);
	    } else {
		Tk_UnmapWindow(oldWindow);
	    }
	}
	if (client != NULL) {
	    client->tkwin = NULL;
	}
	if (ewPtr->body.ew.tkwin != NULL) {
	    Tk_Window ancestor, parent;
	    Tcl_HashEntry *hPtr;
	    int isNew;

	    /*
	     * Make sure that the text is either the parent of the embedded
	     * window or a descendant of that parent. Also, don't allow a
	     * top-level window to be managed inside a text.
	     */

	    parent = Tk_Parent(ewPtr->body.ew.tkwin);
	    for (ancestor = textPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) {
		if (ancestor == parent) {
		    break;
		}
		if (Tk_TopWinHierarchy(ancestor)) {
		badMaster:
		    Tcl_AppendResult(textPtr->interp, "can't embed ",
			    Tk_PathName(ewPtr->body.ew.tkwin), " in ",
			    Tk_PathName(textPtr->tkwin), NULL);
		    ewPtr->body.ew.tkwin = NULL;
		    if (client != NULL) {
			client->tkwin = NULL;
		    }
		    return TCL_ERROR;
		}
	    }
	    if (Tk_TopWinHierarchy(ewPtr->body.ew.tkwin)
		    || (ewPtr->body.ew.tkwin == textPtr->tkwin)) {
		goto badMaster;
	    }

	    if (client == NULL) {
		/*
		 * Have to make the new client.
		 */

		client = (TkTextEmbWindowClient *)
			ckalloc(sizeof(TkTextEmbWindowClient));
		client->next = ewPtr->body.ew.clients;
		client->textPtr = textPtr;
		client->tkwin = NULL;
		client->chunkCount = 0;
		client->displayed = 0;
		client->parent = ewPtr;
		ewPtr->body.ew.clients = client;
	    }
	    client->tkwin = ewPtr->body.ew.tkwin;

	    /*
	     * Take over geometry management for the window, plus create an
	     * event handler to find out when it is deleted.
	     */

	    Tk_ManageGeometry(ewPtr->body.ew.tkwin, &textGeomType, client);
	    Tk_CreateEventHandler(ewPtr->body.ew.tkwin, StructureNotifyMask,
		    EmbWinStructureProc, client);

	    /*
	     * Special trick!  Must enter into the hash table *after* calling
	     * Tk_ManageGeometry: if the window was already managed elsewhere
	     * in this text, the Tk_ManageGeometry call will cause the entry
	     * to be removed, which could potentially lose the new entry.
	     */

	    hPtr = Tcl_CreateHashEntry(&textPtr->sharedTextPtr->windowTable,
		    Tk_PathName(ewPtr->body.ew.tkwin), &isNew);
	    Tcl_SetHashValue(hPtr, ewPtr);
	}
    }
    return TCL_OK;
}
Esempio n. 15
0
static int
ConfigureWinItem(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Canvas canvas,		/* Canvas containing itemPtr. */
    Tk_Item *itemPtr,		/* Window item to reconfigure. */
    int objc,			/* Number of elements in objv.  */
    Tcl_Obj *const objv[],	/* Arguments describing things to configure. */
    int flags)			/* Flags to pass to Tk_ConfigureWidget. */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    Tk_Window oldWindow;
    Tk_Window canvasTkwin;

    oldWindow = winItemPtr->tkwin;
    canvasTkwin = Tk_CanvasTkwin(canvas);
    if (TCL_OK != Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, objc,
	    (const char **) objv, (char *) winItemPtr, flags|TK_CONFIG_OBJS)) {
	return TCL_ERROR;
    }

    /*
     * A few of the options require additional processing.
     */

    if (oldWindow != winItemPtr->tkwin) {
	if (oldWindow != NULL) {
	    Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
		    WinItemStructureProc, winItemPtr);
	    Tk_ManageGeometry(oldWindow, NULL, NULL);
	    Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
	    Tk_UnmapWindow(oldWindow);
	}
	if (winItemPtr->tkwin != NULL) {
	    Tk_Window ancestor, parent;

	    /*
	     * Make sure that the canvas is either the parent of the window
	     * associated with the item or a descendant of that parent. Also,
	     * don't allow a top-of-hierarchy window to be managed inside a
	     * canvas.
	     */

	    parent = Tk_Parent(winItemPtr->tkwin);
	    for (ancestor = canvasTkwin ;; ancestor = Tk_Parent(ancestor)) {
		if (ancestor == parent) {
		    break;
		}
		if (((Tk_FakeWin *) ancestor)->flags & TK_TOP_HIERARCHY) {
		    goto badWindow;
		}
	    }
	    if (((Tk_FakeWin *) winItemPtr->tkwin)->flags & TK_TOP_HIERARCHY){
		goto badWindow;
	    }
	    if (winItemPtr->tkwin == canvasTkwin) {
		goto badWindow;
	    }
	    Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
		    WinItemStructureProc, winItemPtr);
	    Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType, winItemPtr);
	}
    }
    if ((winItemPtr->tkwin != NULL)
	    && (itemPtr->state == TK_STATE_HIDDEN)) {
	if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmapWindow(winItemPtr->tkwin);
	} else {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
    }

    ComputeWindowBbox(canvas, winItemPtr);
    return TCL_OK;

  badWindow:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "can't use %s in a window item of this canvas",
	    Tk_PathName(winItemPtr->tkwin)));
    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
    winItemPtr->tkwin = NULL;
    return TCL_ERROR;
}
Esempio n. 16
0
int
Tk_PlaceObjCmd(
    ClientData clientData,	/* Interpreter main window. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tk_Window main_win = clientData;
    Tk_Window tkwin;
    Slave *slavePtr;
    TkDisplay *dispPtr;
    Tk_OptionTable optionTable;
    static const char *const optionStrings[] = {
	"configure", "forget", "info", "slaves", NULL
    };
    enum options { PLACE_CONFIGURE, PLACE_FORGET, PLACE_INFO, PLACE_SLAVES };
    int index;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "option|pathName args");
	return TCL_ERROR;
    }

    /*
     * Create the option table for this widget class. If it has already been
     * created, the cached pointer will be returned.
     */

     optionTable = Tk_CreateOptionTable(interp, optionSpecs);

    /*
     * Handle special shortcut where window name is first argument.
     */

    if (Tcl_GetString(objv[1])[0] == '.') {
	if (TkGetWindowFromObj(interp, main_win, objv[1],
		&tkwin) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Initialize, if that hasn't been done yet.
	 */

	dispPtr = ((TkWindow *) tkwin)->dispPtr;
	if (!dispPtr->placeInit) {
	    Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
	    Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
	    dispPtr->placeInit = 1;
	}

	return ConfigureSlave(interp, tkwin, optionTable, objc-2, objv+2);
    }

    /*
     * Handle more general case of option followed by window name followed by
     * possible additional arguments.
     */

    if (TkGetWindowFromObj(interp, main_win, objv[2],
	    &tkwin) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Initialize, if that hasn't been done yet.
     */

    dispPtr = ((TkWindow *) tkwin)->dispPtr;
    if (!dispPtr->placeInit) {
	Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS);
	Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS);
	dispPtr->placeInit = 1;
    }

    if (Tcl_GetIndexFromObjStruct(interp, objv[1], optionStrings,
	    sizeof(char *), "option", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case PLACE_CONFIGURE:
	if (objc == 3 || objc == 4) {
	    Tcl_Obj *objPtr;

	    slavePtr = FindSlave(tkwin);
	    if (slavePtr == NULL) {
		return TCL_OK;
	    }
	    objPtr = Tk_GetOptionInfo(interp, (char *) slavePtr, optionTable,
		    (objc == 4) ? objv[3] : NULL, tkwin);
	    if (objPtr == NULL) {
		return TCL_ERROR;
	    }
	    Tcl_SetObjResult(interp, objPtr);
	    return TCL_OK;
	}
	return ConfigureSlave(interp, tkwin, optionTable, objc-3, objv+3);

    case PLACE_FORGET:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	slavePtr = FindSlave(tkwin);
	if (slavePtr == NULL) {
	    return TCL_OK;
	}
	if ((slavePtr->masterPtr != NULL) &&
		(slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
	}
	UnlinkSlave(slavePtr);
	Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable,
		(char *) tkwin));
	Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc,
		slavePtr);
	Tk_ManageGeometry(tkwin, NULL, NULL);
	Tk_UnmapWindow(tkwin);
	FreeSlave(slavePtr);
	break;

    case PLACE_INFO:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	return PlaceInfoCommand(interp, tkwin);

    case PLACE_SLAVES: {
	Master *masterPtr;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "pathName");
	    return TCL_ERROR;
	}
	masterPtr = FindMaster(tkwin);
	if (masterPtr != NULL) {
	    Tcl_Obj *listPtr = Tcl_NewObj();

	    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL;
		    slavePtr = slavePtr->nextPtr) {
		Tcl_ListObjAppendElement(NULL, listPtr,
			TkNewWindowObj(slavePtr->tkwin));
	    }
	    Tcl_SetObjResult(interp, listPtr);
	}
	break;
    }
    }

    return TCL_OK;
}
Esempio n. 17
0
static void
RecomputePlacement(
    ClientData clientData)	/* Pointer to Master record. */
{
    register Master *masterPtr = clientData;
    register Slave *slavePtr;
    int x, y, width, height, tmp;
    int masterWidth, masterHeight, masterX, masterY;
    double x1, y1, x2, y2;
    int abort;			/* May get set to non-zero to abort this
				 * placement operation. */

    masterPtr->flags &= ~PARENT_RECONFIG_PENDING;

    /*
     * Abort any nested call to RecomputePlacement for this window, since
     * we'll do everything necessary here, and set up so this call can be
     * aborted if necessary.
     */

    if (masterPtr->abortPtr != NULL) {
	*masterPtr->abortPtr = 1;
    }
    masterPtr->abortPtr = &abort;
    abort = 0;
    Tcl_Preserve(masterPtr);

    /*
     * Iterate over all the slaves for the master. Each slave's geometry can
     * be computed independently of the other slaves. Changes to the window's
     * structure could cause almost anything to happen, including deleting the
     * parent or child. If this happens, we'll be told to abort.
     */

    for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort;
	    slavePtr = slavePtr->nextPtr) {
	/*
	 * Step 1: compute size and borderwidth of master, taking into account
	 * desired border mode.
	 */

	masterX = masterY = 0;
	masterWidth = Tk_Width(masterPtr->tkwin);
	masterHeight = Tk_Height(masterPtr->tkwin);
	if (slavePtr->borderMode == BM_INSIDE) {
	    masterX = Tk_InternalBorderLeft(masterPtr->tkwin);
	    masterY = Tk_InternalBorderTop(masterPtr->tkwin);
	    masterWidth -= masterX + Tk_InternalBorderRight(masterPtr->tkwin);
	    masterHeight -= masterY +
		    Tk_InternalBorderBottom(masterPtr->tkwin);
	} else if (slavePtr->borderMode == BM_OUTSIDE) {
	    masterX = masterY = -Tk_Changes(masterPtr->tkwin)->border_width;
	    masterWidth -= 2 * masterX;
	    masterHeight -= 2 * masterY;
	}

	/*
	 * Step 2: compute size of slave (outside dimensions including border)
	 * and location of anchor point within master.
	 */

	x1 = slavePtr->x + masterX + (slavePtr->relX*masterWidth);
	x = (int) (x1 + ((x1 > 0) ? 0.5 : -0.5));
	y1 = slavePtr->y + masterY + (slavePtr->relY*masterHeight);
	y = (int) (y1 + ((y1 > 0) ? 0.5 : -0.5));
	if (slavePtr->flags & (CHILD_WIDTH|CHILD_REL_WIDTH)) {
	    width = 0;
	    if (slavePtr->flags & CHILD_WIDTH) {
		width += slavePtr->width;
	    }
	    if (slavePtr->flags & CHILD_REL_WIDTH) {
		/*
		 * The code below is a bit tricky. In order to round correctly
		 * when both relX and relWidth are specified, compute the
		 * location of the right edge and round that, then compute
		 * width. If we compute the width and round it, rounding
		 * errors in relX and relWidth accumulate.
		 */

		x2 = x1 + (slavePtr->relWidth*masterWidth);
		tmp = (int) (x2 + ((x2 > 0) ? 0.5 : -0.5));
		width += tmp - x;
	    }
	} else {
	    width = Tk_ReqWidth(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	}
	if (slavePtr->flags & (CHILD_HEIGHT|CHILD_REL_HEIGHT)) {
	    height = 0;
	    if (slavePtr->flags & CHILD_HEIGHT) {
		height += slavePtr->height;
	    }
	    if (slavePtr->flags & CHILD_REL_HEIGHT) {
		/*
		 * See note above for rounding errors in width computation.
		 */

		y2 = y1 + (slavePtr->relHeight*masterHeight);
		tmp = (int) (y2 + ((y2 > 0) ? 0.5 : -0.5));
		height += tmp - y;
	    }
	} else {
	    height = Tk_ReqHeight(slavePtr->tkwin)
		    + 2*Tk_Changes(slavePtr->tkwin)->border_width;
	}

	/*
	 * Step 3: adjust the x and y positions so that the desired anchor
	 * point on the slave appears at that position. Also adjust for the
	 * border mode and master's border.
	 */

	switch (slavePtr->anchor) {
	case TK_ANCHOR_N:
	    x -= width/2;
	    break;
	case TK_ANCHOR_NE:
	    x -= width;
	    break;
	case TK_ANCHOR_E:
	    x -= width;
	    y -= height/2;
	    break;
	case TK_ANCHOR_SE:
	    x -= width;
	    y -= height;
	    break;
	case TK_ANCHOR_S:
	    x -= width/2;
	    y -= height;
	    break;
	case TK_ANCHOR_SW:
	    y -= height;
	    break;
	case TK_ANCHOR_W:
	    y -= height/2;
	    break;
	case TK_ANCHOR_NW:
	    break;
	case TK_ANCHOR_CENTER:
	    x -= width/2;
	    y -= height/2;
	    break;
	}

	/*
	 * Step 4: adjust width and height again to reflect inside dimensions
	 * of window rather than outside. Also make sure that the width and
	 * height aren't zero.
	 */

	width -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	height -= 2*Tk_Changes(slavePtr->tkwin)->border_width;
	if (width <= 0) {
	    width = 1;
	}
	if (height <= 0) {
	    height = 1;
	}

	/*
	 * Step 5: reconfigure the window and map it if needed. If the slave
	 * is a child of the master, we do this ourselves. If the slave isn't
	 * a child of the master, let Tk_MaintainGeometry do the work (it will
	 * re-adjust things as relevant windows map, unmap, and move).
	 */

	if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) {
	    if ((x != Tk_X(slavePtr->tkwin))
		    || (y != Tk_Y(slavePtr->tkwin))
		    || (width != Tk_Width(slavePtr->tkwin))
		    || (height != Tk_Height(slavePtr->tkwin))) {
		Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height);
	    }
            if (abort) {
                break;
            }

	    /*
	     * Don't map the slave unless the master is mapped: the slave will
	     * get mapped later, when the master is mapped.
	     */

	    if (Tk_IsMapped(masterPtr->tkwin)) {
		Tk_MapWindow(slavePtr->tkwin);
	    }
	} else {
	    if ((width <= 0) || (height <= 0)) {
		Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin);
		Tk_UnmapWindow(slavePtr->tkwin);
	    } else {
		Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin,
			x, y, width, height);
	    }
	}
    }

    masterPtr->abortPtr = NULL;
    Tcl_Release(masterPtr);
}
Esempio n. 18
0
static int
ConfigureSlave(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tk_Window tkwin,		/* Token for the window to manipulate. */
    Tk_OptionTable table,	/* Token for option table. */
    int objc,			/* Number of config arguments. */
    Tcl_Obj *const objv[])	/* Object values for arguments. */
{
    register Master *masterPtr;
    Tk_SavedOptions savedOptions;
    int mask;
    Slave *slavePtr;
    Tk_Window masterWin = (Tk_Window) NULL;

    if (Tk_TopWinHierarchy(tkwin)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't use placer on top-level window \"%s\"; use "
		"wm command instead", Tk_PathName(tkwin)));
	Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "TOPLEVEL", NULL);
	return TCL_ERROR;
    }

    slavePtr = CreateSlave(tkwin, table);

    if (Tk_SetOptions(interp, (char *) slavePtr, table, objc, objv,
	    slavePtr->tkwin, &savedOptions, &mask) != TCL_OK) {
	goto error;
    }

    /*
     * Set slave flags. First clear the field, then add bits as needed.
     */

    slavePtr->flags = 0;
    if (slavePtr->heightPtr) {
	slavePtr->flags |= CHILD_HEIGHT;
    }

    if (slavePtr->relHeightPtr) {
	slavePtr->flags |= CHILD_REL_HEIGHT;
    }

    if (slavePtr->relWidthPtr) {
	slavePtr->flags |= CHILD_REL_WIDTH;
    }

    if (slavePtr->widthPtr) {
	slavePtr->flags |= CHILD_WIDTH;
    }

    if (!(mask & IN_MASK) && (slavePtr->masterPtr != NULL)) {
	/*
	 * If no -in option was passed and the slave is already placed then
	 * just recompute the placement.
	 */

	masterPtr = slavePtr->masterPtr;
	goto scheduleLayout;
    } else if (mask & IN_MASK) {
	/* -in changed */
	Tk_Window tkwin;
	Tk_Window ancestor;

	tkwin = slavePtr->inTkwin;

	/*
	 * Make sure that the new master is either the logical parent of the
	 * slave or a descendant of that window, and that the master and slave
	 * aren't the same.
	 */

	for (ancestor = tkwin; ; ancestor = Tk_Parent(ancestor)) {
	    if (ancestor == Tk_Parent(slavePtr->tkwin)) {
		break;
	    }
	    if (Tk_TopWinHierarchy(ancestor)) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't place %s relative to %s",
			Tk_PathName(slavePtr->tkwin), Tk_PathName(tkwin)));
		Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "HIERARCHY", NULL);
		goto error;
	    }
	}
	if (slavePtr->tkwin == tkwin) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't place %s relative to itself",
		    Tk_PathName(slavePtr->tkwin)));
	    Tcl_SetErrorCode(interp, "TK", "GEOMETRY", "LOOP", NULL);
	    goto error;
	}
	if ((slavePtr->masterPtr != NULL)
		&& (slavePtr->masterPtr->tkwin == tkwin)) {
	    /*
	     * Re-using same old master. Nothing to do.
	     */

	    masterPtr = slavePtr->masterPtr;
	    goto scheduleLayout;
	}
	if ((slavePtr->masterPtr != NULL) &&
		(slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin))) {
	    Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin);
	}
	UnlinkSlave(slavePtr);
	masterWin = tkwin;
    }

    /*
     * If there's no master specified for this slave, use its Tk_Parent.
     */

    if (masterWin == NULL) {
	masterWin = Tk_Parent(slavePtr->tkwin);
	slavePtr->inTkwin = masterWin;
    }

    /*
     * Manage the slave window in this master.
     */

    masterPtr = CreateMaster(masterWin);
    slavePtr->masterPtr = masterPtr;
    slavePtr->nextPtr = masterPtr->slavePtr;
    masterPtr->slavePtr = slavePtr;
    Tk_ManageGeometry(slavePtr->tkwin, &placerType, slavePtr);

    /*
     * Arrange for the master to be re-arranged at the first idle moment.
     */

  scheduleLayout:
    Tk_FreeSavedOptions(&savedOptions);

    if (!(masterPtr->flags & PARENT_RECONFIG_PENDING)) {
	masterPtr->flags |= PARENT_RECONFIG_PENDING;
	Tcl_DoWhenIdle(RecomputePlacement, masterPtr);
    }
    return TCL_OK;

    /*
     * Error while processing some option, cleanup and return.
     */

  error:
    Tk_RestoreSavedOptions(&savedOptions);
    return TCL_ERROR;
}
Esempio n. 19
0
static void
DisplayWinItem(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int regionX, int regionY, int regionWidth, int regionHeight)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    WindowItem *winItemPtr = (WindowItem *) itemPtr;
    int width, height;
    short x, y;
    Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
    Tk_State state = itemPtr->state;

    if (winItemPtr->tkwin == NULL) {
	return;
    }
    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    /*
     * A drawable of None is used by the canvas UnmapNotify handler
     * to indicate that we should no longer display ourselves.
     */
    if (state == TK_STATE_HIDDEN || drawable == None) {
	if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmapWindow(winItemPtr->tkwin);
	} else {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
	return;
    }
    Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
	    (double) winItemPtr->header.y1, &x, &y);
    width = winItemPtr->header.x2 - winItemPtr->header.x1;
    height = winItemPtr->header.y2 - winItemPtr->header.y1;

    /*
     * If the window is completely out of the visible area of the canvas then
     * unmap it. This code used not to be present (why unmap the window if it
     * isn't visible anyway?) but this could cause the window to suddenly
     * reappear if the canvas window got resized.
     */

    if (((x + width) <= 0) || ((y + height) <= 0)
	    || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
	if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	    Tk_UnmapWindow(winItemPtr->tkwin);
	} else {
	    Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
	}
	return;
    }

    /*
     * Reposition and map the window (but in different ways depending on
     * whether the canvas is the window's parent).
     */

    if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
	if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
		|| (width != Tk_Width(winItemPtr->tkwin))
		|| (height != Tk_Height(winItemPtr->tkwin))) {
	    Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
	}
	Tk_MapWindow(winItemPtr->tkwin);
    } else {
	Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
		width, height);
    }
}
Esempio n. 20
0
void
TkTextEmbWinDisplayProc(
    TkText *textPtr,		/* Information about text widget. */
    TkTextDispChunk *chunkPtr,	/* Chunk that is to be drawn. */
    int x,			/* X-position in dst at which to draw this
				 * chunk (differs from the x-position in the
				 * chunk because of scrolling). */
    int y,			/* Top of rectangular bounding box for line:
				 * tells where to draw this chunk in dst
				 * (x-position is in the chunk itself). */
    int lineHeight,		/* Total height of line. */
    int baseline,		/* Offset of baseline from y. */
    Display *display,		/* Display to use for drawing (unused).  */
    Drawable dst,		/* Pixmap or window in which to draw
				 * (unused).  */
    int screenY)		/* Y-coordinate in text window that
				 * corresponds to y. */
{
    int lineX, windowX, windowY, width, height;
    Tk_Window tkwin;
    TkTextSegment *ewPtr = chunkPtr->clientData;
    TkTextEmbWindowClient *client = EmbWinGetClient(textPtr, ewPtr);

    if (client == NULL) {
	return;
    }

    tkwin = client->tkwin;
    if (tkwin == NULL) {
	return;
    }

    if ((x + chunkPtr->width) <= 0) {
	/*
	 * The window is off-screen; just unmap it.
	 */

	if (textPtr->tkwin != Tk_Parent(tkwin)) {
	    Tk_UnmaintainGeometry(tkwin, textPtr->tkwin);
	} else {
	    Tk_UnmapWindow(tkwin);
	}
	return;
    }

    /*
     * Compute the window's location and size in the text widget, taking into
     * account the align and stretch values for the window.
     */

    EmbWinBboxProc(textPtr, chunkPtr, 0, screenY, lineHeight, baseline,
	    &lineX, &windowY, &width, &height);
    windowX = lineX - chunkPtr->x + x;

    if (textPtr->tkwin == Tk_Parent(tkwin)) {
	if ((windowX != Tk_X(tkwin)) || (windowY != Tk_Y(tkwin))
		|| (Tk_ReqWidth(tkwin) != Tk_Width(tkwin))
		|| (height != Tk_Height(tkwin))) {
	    Tk_MoveResizeWindow(tkwin, windowX, windowY, width, height);
	}
	Tk_MapWindow(tkwin);
    } else {
	Tk_MaintainGeometry(tkwin, textPtr->tkwin, windowX, windowY,
		width, height);
    }

    /*
     * Mark the window as displayed so that it won't get unmapped.
     */

    client->displayed = 1;
}
Esempio n. 21
0
static void
imfsample_display(ClientData cldata)
{
    char *str;
    int row, col, namex, namey, n, sx, sy, update = FALSE, done;
    Imfsample *imfsample = (Imfsample *) cldata;
    Display *dpy = imfsample->display;
    Tk_Window tkwin = imfsample->tkwin;
    GC gc;
    Pixmap pm = None;
    Drawable d;
    Tk_Font tkfont;
    int winwidth = Tk_Width(Tk_Parent(tkwin)); 
    int winheight = Tk_Height(Tk_Parent(tkwin));
    char tclbuf[100];
    int rslt;
	
    imfsample->update_pending = 0;
    if (!Tk_IsMapped(tkwin)) {
	return;
    }
    /* Check if we need to redraw the entire imfsample. */
    if (imfsample->imfapp) {
	if (imfsample->oldfirst != imfsample->firstvisrow
	    || imfsample->redraw) {
		imfsample->oldfirst = imfsample->firstvisrow;
		update = TRUE;
	}
    }
    /* Create a pixmap for double-buffering if necessary. */
    if (imfsample->double_buffer) {
	update = TRUE;
	pm = Tk_GetPixmap(imfsample->display, Tk_WindowId(tkwin),
			  Tk_Width(tkwin), Tk_Height(tkwin),
			  DefaultDepthOfScreen(Tk_Screen(tkwin)));
	d = pm;
    } else {
	d = Tk_WindowId(tkwin);
    }
    if (black_color == NULL) {
	black_color = Tk_GetColor(interp, tkwin, Tk_GetUid("black"));
    }
    if (white_color == NULL) {
	white_color = Tk_GetColor(interp, tkwin, Tk_GetUid("white"));
    }
    if (black_border == NULL) {
	black_border = Tk_Get3DBorder(interp, tkwin, "black");
    }
    if (white_border == NULL) {
	white_border = Tk_Get3DBorder(interp, tkwin, "white");
    }
    /* Collect GC and font for subsequent work. */
    gc = imfsample->gc;
    XSetClipMask(dpy, gc, None);
    if (imfsample->show_names) {
#ifdef WIN32
	tkfont = Tk_GetFont(interp, tkwin, "-family arial -size 8");
#elif defined (MAC)
	tkfont = Tk_GetFont(interp, tkwin, "-family helvetica -size 11");
#else
	tkfont = Tk_GetFont(interp, tkwin, "-family helvetica -size 12");
#endif
	XSetFont(imfsample->display, gc, Tk_FontId(tkfont));
    }

    /* Redraw the entire widget background/border, but not if we
       are just updating the selected image. */
    if (imfsample->selected == imfsample->previous
     	/* Always redraw if we have only one image (e.g. closeups). */
    	|| (imfsample->numimages == 1 && imfsample->selected == -1)
    	|| update) {
	    done = FALSE;
	    if (imfsample->with_terrain >= 0
	    	/* Terrain tiles are not supported on Windows yet. */
	    	&& use_clip_mask) {
		ImageFamily *timf = 
		    imfsample->imf_list[imfsample->with_terrain];
		Image *timg;
		TkImage *tkimg;

		timg = best_image(timf, 64, 64);
		if (timg) {
		    tkimg = (TkImage *) timg->hook;
		    if (tkimg && tkimg->colr) {
			XSetFillStyle(dpy, gc, FillTiled);
			XSetTile(dpy, gc, tkimg->colr);
			XFillRectangle(dpy, d, gc, 0, 0,
				       Tk_Width(tkwin), Tk_Height(tkwin));
			done = TRUE;
		    }
		}
	    }
	    if (!done) {
		Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 0, 0,
				   Tk_Width(tkwin), Tk_Height(tkwin),
				   imfsample->border_width, imfsample->relief);
	    }
    }
#if 0
    for (i = 0; i < imfsample->numimages; i++) {
	if (imf_interp_hook)
	  imfsample->imf_list[i] =
	    (*imf_interp_hook)(imfsample->imf_list[i], NULL, TRUE);
    }
#endif
    /* Tweak the default item width/height to something better. */
    if (imfsample->iheight == 0) {
	imfsample->iheight = 32;
	if (imfsample->numimages == 1)
	  imfsample->iheight = imfsample->height;
    }
    if (imfsample->iwidth == 0) {
	imfsample->iwidth = 32;
	if (imfsample->numimages == 1)
	  imfsample->iwidth = imfsample->width;
    }
    imfsample->eltw = imfsample->iwidth;
    if (imfsample->show_grid)
      imfsample->eltw += 2;
    else
      imfsample->eltw += 2 * imfsample->pad;
    if (imfsample->show_names && !imfsample->show_grid)
      imfsample->eltw += 80;
    imfsample->elth = imfsample->iheight;
    if (imfsample->show_grid)
      imfsample->elth += 2;
    else
      imfsample->elth += 2 * imfsample->pad;
    /* Fix a lower bound on the vertical spacing. */
    /* (should be determined by choice of app font) */
    if (imfsample->elth < 10 && !imfsample->show_grid)
      imfsample->elth = 10;
    /* Compute and save the number of columns to use. */
    imfsample->cols = winwidth / imfsample->eltw;
    if (imfsample->cols <= 0)
      imfsample->cols = 1;
    /* We can get a little wider spacing by recalculating the element
       width. */
    if (imfsample->show_names && !imfsample->show_grid)
      imfsample->eltw = (winwidth - 10) / imfsample->cols;
    imfsample->rows = imfsample->numimages / imfsample->cols;
    /* Account for a last partial row. */
    if (imfsample->rows * imfsample->cols < imfsample->numimages)
      ++(imfsample->rows);
    /* Compute the number of visible rows.  It would be time-consuming
       to render all the images, so try to do only the visible ones. */
    imfsample->numvisrows = winheight / imfsample->elth;
    if (imfsample->numvisrows > imfsample->rows)
      imfsample->numvisrows = imfsample->rows;
    if (imfsample->numvisrows < 1)
      imfsample->numvisrows = min(1, imfsample->rows);
    if (imfsample->firstvisrow + imfsample->numvisrows > imfsample->rows)
      imfsample->firstvisrow = imfsample->rows - imfsample->numvisrows;
    /* Imfapp-specific code that adjusts the canvas content to fit a resized
    window and also sets the canvas scrollregion correctly. */
    if (imfsample->imfapp
    	&& imfsample->redraw) {  
	    imfsample->width = Tk_Width(Tk_Parent(tkwin));
	    imfsample->height = imfsample->rows * imfsample->elth + 7;
	    Tk_GeometryRequest(tkwin, imfsample->width, imfsample->height);
	    /* There must be a better way to do this ... */
	    sprintf(tclbuf, 
		    ".images.canvas configure -scrollregion [ list 0 0 0 %d ]", 
		    imfsample->height);
	    rslt = Tcl_Eval(interp, tclbuf);
	    if (rslt == TCL_ERROR) {
	        fprintf(stderr, "Error: %s\n", Tcl_GetStringResult(interp));
	    }
	    /* Force a redraw of the scrollbar if the window was resized. */
	    if (imfsample->numimages) {
		sprintf(tclbuf, ".images.canvas.content yview scroll 0 units");
	    } else {
		sprintf(tclbuf, ".images.scroll set 0 1");
	   }
	    rslt = Tcl_Eval(interp, tclbuf);
	    if (rslt == TCL_ERROR) {
	      fprintf(stderr, "Error: %s\n", Tcl_GetStringResult(interp));
	    }
    }
    /* Now iterate through all the images we want to draw. */
    for (row = imfsample->firstvisrow;
	 row <= (imfsample->firstvisrow + imfsample->numvisrows);
	 ++row) {
	if (row < 0)
	  continue;
	for (col = 0; col < imfsample->cols; ++col) {
	    n = row * imfsample->cols + col;
	    if (n >= imfsample->numimages)
	      break;
	    sx = col * imfsample->eltw;
	    sy = (row - imfsample->firstvisrow) * imfsample->elth;
	    /* Erase the old selected imf if we picked a new one. */
	    if (n == imfsample->previous && n != imfsample->selected) {
		done = FALSE; 
		if (imfsample->with_terrain >= 0
		      /* Terrain tiles are not supported on Windows yet. */
		    && use_clip_mask) {
		    ImageFamily *timf = 
			imfsample->imf_list[imfsample->with_terrain];
		    Image *timg;
		    TkImage *tkimg;

		    timg = best_image(timf, 64, 64);
		    if (timg) {
			tkimg = (TkImage *) timg->hook;
			if (tkimg && tkimg->colr) {
			    XSetFillStyle(dpy, gc, FillTiled);
			    XSetTile(dpy, gc, tkimg->colr);
			    if (imfsample->show_grid) {
				XFillRectangle(dpy, d, gc, sx, sy + 2,
					       imfsample->eltw, 
					       imfsample->elth);
			    } else {
				XFillRectangle(dpy, d, gc, sx, sy + 7,
					       imfsample->eltw, 
					       imfsample->elth);
			    }
			    done = TRUE;
			}
		    }
		}
		if (!done) {
		    if (imfsample->show_grid) {
			Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 
					   sx, sy + 2,
					   imfsample->eltw, imfsample->elth,
					   imfsample->border_width, 
					   imfsample->relief);
		    } else {
			Tk_Fill3DRectangle(tkwin, d, imfsample->bg_border, 
					   sx, sy + 7,
					   imfsample->eltw, imfsample->elth,
					   imfsample->border_width, 
					   imfsample->relief);
		    }
		}
	    }
	    /* Just draw the old erased image if we selected a new one, else
	       draw every image. */
	    if (imfsample->selected == imfsample->previous
            	|| n == imfsample->previous
           	|| update) {
		    if (imfsample->show_grid) {
			Tk_Fill3DRectangle(tkwin, d, imfsample->cu_border,
				sx + 2, sy + 2,
				imfsample->iwidth, imfsample->iheight,
				imfsample->border_width, imfsample->relief);
			draw_one_main_image(imfsample, d, gc, 
					    imfsample->imf_list[n],
					    sx + 2, sy + 2,
					    imfsample->iwidth, 
					    imfsample->iheight);
		    } else {
			draw_one_main_image(imfsample, d, gc, 
					    imfsample->imf_list[n],
					    sx + imfsample->pad, 
					    sy + imfsample->pad,
					    imfsample->iwidth, 
					    imfsample->iheight);
		    }
		    if (imfsample->show_names && !imfsample->show_grid) {
			namex = sx + 5;
			namey = sy + imfsample->elth + 3;
			XSetClipMask(dpy, gc, None);
			XSetFillStyle(dpy, gc, FillSolid);
			XSetForeground(dpy, gc, 
				       Tk_3DBorderColor(
					imfsample->fg_border)->pixel);
			str = imfsample->imf_list[n]->name;
			Tk_DrawChars(dpy, d, gc, tkfont, str, strlen(str),
				     namex, namey);
		    }
	    }
	    /* Box the selected imf. */
	    if (n == imfsample->selected) {
		XSetClipMask(dpy, gc, None);
		XSetFillStyle(dpy, gc, FillSolid);
		XSetForeground(dpy, gc, Tk_3DBorderColor(imfsample->fg_border)->pixel);
	  	if (imfsample->show_grid) {
		/* A rectangle on the Mac is 1 pixel smaller in both directions. */
#ifdef MAC
			XDrawRectangle(dpy, d, gc, sx + 2, sy + 2,
				       imfsample->eltw - 2, imfsample->elth - 2);
#else
			XDrawRectangle(dpy, d, gc, sx + 2, sy + 2,
				       imfsample->eltw - 3, imfsample->elth - 3);
#endif
	  	} else {
#ifdef MAC
			XDrawRectangle(dpy, d, gc, sx, sy + 7,
				       imfsample->eltw, imfsample->elth);
#else
			XDrawRectangle(dpy, d, gc, sx, sy + 7,
				       imfsample->eltw - 1, imfsample->elth - 1);
#endif
		}
	    }
	}
    }
    /* Reset the old selected image to the new one if it exists. */
    if (imfsample->selected != -1) {
	imfsample->previous = imfsample->selected;
    }
    /* Reset the redraw flag. */
    imfsample->redraw = FALSE;
    /* If double-buffered, copy to the screen and release the pixmap.  */
    if (imfsample->double_buffer) {
	XCopyArea(imfsample->display, pm, Tk_WindowId(tkwin),
		  imfsample->copygc,
		  0, 0, (unsigned) winwidth, (unsigned) winheight, 0, 0);
	Tk_FreePixmap(imfsample->display, pm);
    }
    if (imfsample->show_names) {
	Tk_FreeFont(tkfont);
    }
    /* In theory this shouldn't be necessary, but in practice the
       interface widgets (esp. the progress bar fill color) are
       affected by the last value of the foreground left over from
       drawing, so set to a consistent value. */
    /* (Note that as of 2000-09-16, some color errors persist, so
       this might not really be necessary -sts) */
    XSetForeground(imfsample->display, imfsample->gc, black_color->pixel);
    XSetBackground(imfsample->display, imfsample->gc, white_color->pixel);
    XSetForeground(imfsample->display, imfsample->copygc, black_color->pixel);
    XSetBackground(imfsample->display, imfsample->copygc, white_color->pixel);
}