summaryrefslogtreecommitdiffstats
path: root/generic/tkFrame.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkFrame.c')
-rw-r--r--generic/tkFrame.c436
1 files changed, 332 insertions, 104 deletions
diff --git a/generic/tkFrame.c b/generic/tkFrame.c
index c5e50b6..1d93976 100644
--- a/generic/tkFrame.c
+++ b/generic/tkFrame.c
@@ -5,8 +5,8 @@
* for the Tk toolkit. Frames are windows with a background color and
* possibly a 3-D effect, but not much else in the way of attributes.
*
- * Copyright (c) 1990-1994 The Regents of the University of California.
- * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ * Copyright © 1990-1994 The Regents of the University of California.
+ * Copyright © 1994-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -94,6 +94,16 @@ typedef struct {
* pixels of extra space to leave above and
* below child area. */
int padY; /* Integer value corresponding to padYPtr. */
+ Tcl_Obj *bgimgPtr; /* Value of -backgroundimage option: specifies
+ * image to display on window's background, or
+ * NULL if none. */
+ Tk_Image bgimg; /* Derived from bgimgPtr by calling
+ * Tk_GetImage, or NULL if bgimgPtr is
+ * NULL. */
+ int tile; /* Whether to tile the bgimg. */
+#ifndef TK_NO_DOUBLE_BUFFERING
+ GC copyGC; /* GC for copying when double-buffering. */
+#endif /* TK_NO_DOUBLE_BUFFERING */
} Frame;
/*
@@ -174,80 +184,94 @@ static const char *const labelAnchorStrings[] = {
static const Tk_OptionSpec commonOptSpec[] = {
{TK_OPTION_BORDER, "-background", "background", "Background",
- DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border),
+ DEF_FRAME_BG_COLOR, TCL_INDEX_NONE, offsetof(Frame, border),
TK_OPTION_NULL_OK, DEF_FRAME_BG_MONO, 0},
{TK_OPTION_SYNONYM, "-bg", NULL, NULL,
- NULL, 0, -1, 0, "-background", 0},
+ NULL, 0, TCL_INDEX_NONE, 0, "-background", 0},
{TK_OPTION_STRING, "-colormap", "colormap", "Colormap",
- DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName),
+ DEF_FRAME_COLORMAP, TCL_INDEX_NONE, offsetof(Frame, colormapName),
TK_OPTION_NULL_OK, 0, 0},
/*
* Having -container is useless in a labelframe since a container has
* no border. It should be deprecated.
*/
{TK_OPTION_BOOLEAN, "-container", "container", "Container",
- DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer), 0, 0, 0},
+ DEF_FRAME_CONTAINER, TCL_INDEX_NONE, offsetof(Frame, isContainer), 0, 0, 0},
{TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor),
+ DEF_FRAME_CURSOR, TCL_INDEX_NONE, offsetof(Frame, cursor),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_PIXELS, "-height", "height", "Height",
- DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height), 0, 0, 0},
+ DEF_FRAME_HEIGHT, TCL_INDEX_NONE, offsetof(Frame, height), 0, 0, 0},
{TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1,
- Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0},
+ "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, TCL_INDEX_NONE,
+ offsetof(Frame, highlightBgColorPtr), 0, 0, 0},
{TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_FRAME_HIGHLIGHT, -1, Tk_Offset(Frame, highlightColorPtr),
+ DEF_FRAME_HIGHLIGHT, TCL_INDEX_NONE, offsetof(Frame, highlightColorPtr),
0, 0, 0},
{TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, -1,
- Tk_Offset(Frame, highlightWidth), 0, 0, 0},
+ "HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, TCL_INDEX_NONE,
+ offsetof(Frame, highlightWidth), 0, 0, 0},
{TK_OPTION_PIXELS, "-padx", "padX", "Pad",
- DEF_FRAME_PADX, Tk_Offset(Frame, padXPtr),
- Tk_Offset(Frame, padX), 0, 0, 0},
+ DEF_FRAME_PADX, offsetof(Frame, padXPtr),
+ offsetof(Frame, padX), 0, 0, 0},
{TK_OPTION_PIXELS, "-pady", "padY", "Pad",
- DEF_FRAME_PADY, Tk_Offset(Frame, padYPtr),
- Tk_Offset(Frame, padY), 0, 0, 0},
+ DEF_FRAME_PADY, offsetof(Frame, padYPtr),
+ offsetof(Frame, padY), 0, 0, 0},
{TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_FRAME_TAKE_FOCUS, -1, Tk_Offset(Frame, takeFocus),
+ DEF_FRAME_TAKE_FOCUS, TCL_INDEX_NONE, offsetof(Frame, takeFocus),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-visual", "visual", "Visual",
- DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName),
+ DEF_FRAME_VISUAL, TCL_INDEX_NONE, offsetof(Frame, visualName),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_PIXELS, "-width", "width", "Width",
- DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width), 0, 0, 0},
+ DEF_FRAME_WIDTH, TCL_INDEX_NONE, offsetof(Frame, width), 0, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0}
};
static const Tk_OptionSpec frameOptSpec[] = {
+ {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage",
+ DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_SYNONYM, "-bd", NULL, NULL,
- NULL, 0, -1, 0, "-borderwidth", 0},
+ NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL,
+ NULL, 0, TCL_INDEX_NONE, 0, "-backgroundimage", 0},
{TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
+ DEF_FRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth), 0, 0, 0},
{TK_OPTION_STRING, "-class", "class", "Class",
- DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ DEF_FRAME_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ DEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
+ {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile",
+ DEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), 0, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL,
NULL, 0, 0, 0, commonOptSpec, 0}
};
static const Tk_OptionSpec toplevelOptSpec[] = {
+ {TK_OPTION_STRING, "-backgroundimage", "backgroundImage", "BackgroundImage",
+ DEF_FRAME_BG_IMAGE, offsetof(Frame, bgimgPtr), TCL_INDEX_NONE,
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_SYNONYM, "-bd", NULL, NULL,
- NULL, 0, -1, 0, "-borderwidth", 0},
+ NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
+ {TK_OPTION_SYNONYM, "-bgimg", NULL, NULL,
+ NULL, 0, TCL_INDEX_NONE, 0, "-backgroundimage", 0},
{TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth), 0, 0, 0},
+ DEF_FRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth), 0, 0, 0},
{TK_OPTION_STRING, "-class", "class", "Class",
- DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ DEF_TOPLEVEL_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
{TK_OPTION_STRING, "-menu", "menu", "Menu",
- DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName),
+ DEF_TOPLEVEL_MENU, TCL_INDEX_NONE, offsetof(Frame, menuName),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ DEF_FRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
{TK_OPTION_STRING, "-screen", "screen", "Screen",
- DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName),
+ DEF_TOPLEVEL_SCREEN, TCL_INDEX_NONE, offsetof(Frame, screenName),
TK_OPTION_NULL_OK, 0, 0},
+ {TK_OPTION_BOOLEAN, "-tile", "tile", "Tile",
+ DEF_FRAME_BG_TILE, TCL_INDEX_NONE, offsetof(Frame, tile), 0, 0, 0},
{TK_OPTION_STRING, "-use", "use", "Use",
- DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis),
+ DEF_TOPLEVEL_USE, TCL_INDEX_NONE, offsetof(Frame, useThis),
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL,
NULL, 0, 0, 0, commonOptSpec, 0}
@@ -255,27 +279,27 @@ static const Tk_OptionSpec toplevelOptSpec[] = {
static const Tk_OptionSpec labelframeOptSpec[] = {
{TK_OPTION_SYNONYM, "-bd", NULL, NULL,
- NULL, 0, -1, 0, "-borderwidth", 0},
+ NULL, 0, TCL_INDEX_NONE, 0, "-borderwidth", 0},
{TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
+ DEF_LABELFRAME_BORDER_WIDTH, TCL_INDEX_NONE, offsetof(Frame, borderWidth),
0, 0, 0},
{TK_OPTION_STRING, "-class", "class", "Class",
- DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className), 0, 0, 0},
+ DEF_LABELFRAME_CLASS, TCL_INDEX_NONE, offsetof(Frame, className), 0, 0, 0},
{TK_OPTION_SYNONYM, "-fg", "foreground", NULL,
- NULL, 0, -1, 0, "-foreground", 0},
+ NULL, 0, TCL_INDEX_NONE, 0, "-foreground", 0},
{TK_OPTION_FONT, "-font", "font", "Font",
- DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0},
+ DEF_LABELFRAME_FONT, TCL_INDEX_NONE, offsetof(Labelframe, tkfont), 0, 0, 0},
{TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
- DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0},
+ DEF_LABELFRAME_FG, TCL_INDEX_NONE, offsetof(Labelframe, textColorPtr), 0, 0, 0},
{TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor",
- DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor),
+ DEF_LABELFRAME_LABELANCHOR, TCL_INDEX_NONE, offsetof(Labelframe, labelAnchor),
0, labelAnchorStrings, 0},
{TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget",
- NULL, -1, Tk_Offset(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},
+ NULL, TCL_INDEX_NONE, offsetof(Labelframe, labelWin), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief), 0, 0, 0},
+ DEF_LABELFRAME_RELIEF, TCL_INDEX_NONE, offsetof(Frame, relief), 0, 0, 0},
{TK_OPTION_STRING, "-text", "text", "Text",
- DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1,
+ DEF_LABELFRAME_TEXT, offsetof(Labelframe, textPtr), TCL_INDEX_NONE,
TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL,
NULL, 0, 0, 0, commonOptSpec, 0}
@@ -304,13 +328,19 @@ static const Tk_OptionSpec *const optionSpecs[] = {
static void ComputeFrameGeometry(Frame *framePtr);
static int ConfigureFrame(Tcl_Interp *interp, Frame *framePtr,
- int objc, Tcl_Obj *const objv[]);
+ Tcl_Size objc, Tcl_Obj *const objv[]);
static int CreateFrame(void *clientData, Tcl_Interp *interp,
- int objc, Tcl_Obj *const objv[],
+ Tcl_Size objc, Tcl_Obj *const objv[],
enum FrameType type, const char *appName);
static Tcl_FreeProc DestroyFrame;
static void DestroyFramePartly(Frame *framePtr);
static void DisplayFrame(void *clientData);
+static void DrawFrameBackground(Tk_Window tkwin, Pixmap pixmap,
+ int highlightWidth, int borderWidth,
+ Tk_Image bgimg, int bgtile);
+static void FrameBgImageProc(void *clientData,
+ int x, int y, int width, int height,
+ int imgWidth, int imgHeight);
static void FrameCmdDeletedProc(void *clientData);
static void FrameEventProc(void *clientData,
XEvent *eventPtr);
@@ -320,9 +350,7 @@ static void FrameRequestProc(void *clientData,
Tk_Window tkwin);
static void FrameStructureProc(void *clientData,
XEvent *eventPtr);
-static int FrameWidgetObjCmd(void *clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *const objv[]);
+static Tcl_ObjCmdProc FrameWidgetObjCmd;
static void FrameWorldChanged(void *instanceData);
static void MapFrame(void *clientData);
@@ -421,7 +449,7 @@ int
TkCreateFrame(
void *clientData, /* Either NULL or pointer to option table. */
Tcl_Interp *interp, /* Current interpreter. */
- int argc, /* Number of arguments. */
+ Tcl_Size argc, /* Number of arguments. */
const char *const *argv, /* Argument strings. */
int toplevel, /* Non-zero means create a toplevel window,
* zero means create a frame. */
@@ -430,11 +458,12 @@ TkCreateFrame(
* Gives the base name to use for the new
* application. */
{
- int result, i;
+ int result;
+ Tcl_Size i;
Tcl_Obj **objv = (Tcl_Obj **)ckalloc((argc+1) * sizeof(Tcl_Obj **));
for (i=0; i<argc; i++) {
- objv[i] = Tcl_NewStringObj(argv[i], -1);
+ objv[i] = Tcl_NewStringObj(argv[i], TCL_INDEX_NONE);
Tcl_IncrRefCount(objv[i]);
}
objv[argc] = NULL;
@@ -459,7 +488,7 @@ TkListCreateFrame(
* Gives the base name to use for the new
* application. */
{
- int objc;
+ Tcl_Size objc;
Tcl_Obj **objv;
if (TCL_OK != Tcl_ListObjGetElements(interp, listObj, &objc, &objv)) {
@@ -474,7 +503,7 @@ static int
CreateFrame(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Current interpreter. */
- int objc, /* Number of arguments. */
+ Tcl_Size objc, /* Number of arguments. */
Tcl_Obj *const objv[], /* Argument objects. */
enum FrameType type, /* What widget type to create. */
const char *appName) /* Should only be non-NULL if there are no
@@ -488,8 +517,8 @@ CreateFrame(
Tk_Window newWin;
const char *className, *screenName, *visualName, *colormapName;
const char *arg, *useOption;
- int i, depth;
- int length;
+ int depth;
+ Tcl_Size i, length;
unsigned int mask;
Colormap colormap;
Visual *visual;
@@ -548,8 +577,8 @@ CreateFrame(
* correct class.
* 2. Must set visual information before calling ConfigureFrame so that
* colors are allocated in a proper colormap.
- * 3. Must call TkpUseWindow before setting non-default visual
- * information, since TkpUseWindow changes the defaults.
+ * 3. Must call Tk_UseWindow before setting non-default visual
+ * information, since Tk_UseWindow changes the defaults.
*/
if (screenName == NULL) {
@@ -603,7 +632,7 @@ CreateFrame(
useOption = Tk_GetOption(newWin, "use", "Use");
}
if ((useOption != NULL) && (*useOption != 0)
- && (TkpUseWindow(interp, newWin, useOption) != TCL_OK)) {
+ && (Tk_UseWindow(interp, newWin, useOption) != TCL_OK)) {
goto error;
}
if (visualName == NULL) {
@@ -683,7 +712,7 @@ CreateFrame(
mask |= ActivateMask;
}
Tk_CreateEventHandler(newWin, mask, FrameEventProc, framePtr);
- if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, newWin)
+ if ((Tk_InitOptions(interp, framePtr, optionTable, newWin)
!= TCL_OK) ||
(ConfigureFrame(interp, framePtr, objc-2, objv+2) != TCL_OK)) {
goto error;
@@ -692,16 +721,16 @@ CreateFrame(
if (framePtr->useThis != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"windows cannot have both the -use and the -container"
- " option set", -1));
+ " option set", TCL_INDEX_NONE));
Tcl_SetErrorCode(interp, "TK", "FRAME", "CONTAINMENT", NULL);
goto error;
}
- TkpMakeContainer(framePtr->tkwin);
+ Tk_MakeContainer(framePtr->tkwin);
}
if (type == TYPE_TOPLEVEL) {
Tcl_DoWhenIdle(MapFrame, framePtr);
}
- Tcl_SetObjResult(interp, TkNewWindowObj(newWin));
+ Tcl_SetObjResult(interp, Tk_NewWindowObj(newWin));
return TCL_OK;
error:
@@ -744,8 +773,8 @@ FrameWidgetObjCmd(
};
Frame *framePtr = (Frame *)clientData;
int result = TCL_OK, index;
- int c, i;
- int length;
+ int c;
+ Tcl_Size i, length;
Tcl_Obj *objPtr;
if (objc < 2) {
@@ -764,7 +793,7 @@ FrameWidgetObjCmd(
result = TCL_ERROR;
goto done;
}
- objPtr = Tk_GetOptionValue(interp, (char *) framePtr,
+ objPtr = Tk_GetOptionValue(interp, framePtr,
framePtr->optionTable, objv[2], framePtr->tkwin);
if (objPtr == NULL) {
result = TCL_ERROR;
@@ -774,7 +803,7 @@ FrameWidgetObjCmd(
break;
case FRAME_CONFIGURE:
if (objc <= 3) {
- objPtr = Tk_GetOptionInfo(interp, (char *) framePtr,
+ objPtr = Tk_GetOptionInfo(interp, framePtr,
framePtr->optionTable, (objc == 3) ? objv[2] : NULL,
framePtr->tkwin);
if (objPtr == NULL) {
@@ -812,7 +841,7 @@ FrameWidgetObjCmd(
if (c == 'u') {
const char *string = Tcl_GetString(objv[i+1]);
- if (TkpUseWindow(interp, framePtr->tkwin,
+ if (Tk_UseWindow(interp, framePtr->tkwin,
string) != TCL_OK) {
result = TCL_ERROR;
goto done;
@@ -859,7 +888,11 @@ FrameWidgetObjCmd(
static void
DestroyFrame(
- char *memPtr) /* Info about frame widget. */
+#if TCL_MAJOR_VERSION > 8
+ void *memPtr) /* Info about frame widget. */
+#else
+ char *memPtr)
+#endif
{
Frame *framePtr = (Frame *)memPtr;
Labelframe *labelframePtr = (Labelframe *)memPtr;
@@ -870,9 +903,17 @@ DestroyFrame(
Tk_FreeGC(framePtr->display, labelframePtr->textGC);
}
}
+#ifndef TK_NO_DOUBLE_BUFFERING
+ if (framePtr->copyGC != NULL) {
+ Tk_FreeGC(framePtr->display, framePtr->copyGC);
+ }
+#endif /* TK_NO_DOUBLE_BUFFERING */
if (framePtr->colormap != None) {
Tk_FreeColormap(framePtr->display, framePtr->colormap);
}
+ if (framePtr->bgimg) {
+ Tk_FreeImage(framePtr->bgimg);
+ }
ckfree(framePtr);
}
@@ -911,7 +952,7 @@ DestroyFramePartly(
labelframePtr->labelWin = NULL;
}
- Tk_FreeConfigOptions((char *) framePtr, framePtr->optionTable,
+ Tk_FreeConfigOptions(framePtr, framePtr->optionTable,
framePtr->tkwin);
}
@@ -940,13 +981,14 @@ ConfigureFrame(
Tcl_Interp *interp, /* Used for error reporting. */
Frame *framePtr, /* Information about widget; may or may not
* already have values for some fields. */
- int objc, /* Number of valid entries in objv. */
+ Tcl_Size objc, /* Number of valid entries in objv. */
Tcl_Obj *const objv[]) /* Arguments. */
{
Tk_SavedOptions savedOptions;
char *oldMenuName;
Tk_Window oldWindow = NULL;
Labelframe *labelframePtr = (Labelframe *) framePtr;
+ Tk_Image image = NULL;
/*
* Need the old menubar name for the menu code to delete it.
@@ -962,7 +1004,7 @@ ConfigureFrame(
if (framePtr->type == TYPE_LABELFRAME) {
oldWindow = labelframePtr->labelWin;
}
- if (Tk_SetOptions(interp, (char *) framePtr,
+ if (Tk_SetOptions(interp, framePtr,
framePtr->optionTable, objc, objv,
framePtr->tkwin, &savedOptions, NULL) != TCL_OK) {
if (oldMenuName != NULL) {
@@ -970,6 +1012,20 @@ ConfigureFrame(
}
return TCL_ERROR;
}
+
+ if (framePtr->bgimgPtr) {
+ image = Tk_GetImage(interp, framePtr->tkwin,
+ Tcl_GetString(framePtr->bgimgPtr), FrameBgImageProc, framePtr);
+ if (image == NULL) {
+ Tk_RestoreSavedOptions(&savedOptions);
+ return TCL_ERROR;
+ }
+ }
+ if (framePtr->bgimg) {
+ Tk_FreeImage(framePtr->bgimg);
+ }
+ framePtr->bgimg = image;
+
Tk_FreeSavedOptions(&savedOptions);
/*
@@ -981,7 +1037,7 @@ ConfigureFrame(
|| ((oldMenuName != NULL) && (framePtr->menuName != NULL)
&& strcmp(oldMenuName, framePtr->menuName) != 0))
&& framePtr->type == TYPE_TOPLEVEL) {
- TkSetWindowMenuBar(interp, framePtr->tkwin, oldMenuName,
+ Tk_SetWindowMenubar(interp, framePtr->tkwin, oldMenuName,
framePtr->menuName);
}
@@ -1111,6 +1167,15 @@ FrameWorldChanged(
anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) &&
(labelframePtr->labelWin != NULL);
+#ifndef TK_NO_DOUBLE_BUFFERING
+ gcValues.graphics_exposures = False;
+ gc = Tk_GetGC(tkwin, GCGraphicsExposures, &gcValues);
+ if (framePtr->copyGC != NULL) {
+ Tk_FreeGC(framePtr->display, framePtr->copyGC);
+ }
+ framePtr->copyGC = gc;
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
if (framePtr->type == TYPE_LABELFRAME) {
/*
* The textGC is needed even in the labelWin case, so it's always
@@ -1138,7 +1203,7 @@ FrameWorldChanged(
Tk_FreeTextLayout(labelframePtr->textLayout);
labelframePtr->textLayout =
Tk_ComputeTextLayout(labelframePtr->tkfont,
- labelText, -1, 0, TK_JUSTIFY_CENTER, 0,
+ labelText, TCL_INDEX_NONE, 0, TK_JUSTIFY_CENTER, 0,
&labelframePtr->labelReqWidth,
&labelframePtr->labelReqHeight);
labelframePtr->labelReqWidth += 2 * LABELSPACING;
@@ -1439,10 +1504,10 @@ DisplayFrame(
if (framePtr->flags & GOT_FOCUS) {
fgGC = Tk_GCForColor(framePtr->highlightColorPtr,
Tk_WindowId(tkwin));
- TkpDrawHighlightBorder(tkwin, fgGC, bgGC, hlWidth,
+ Tk_DrawHighlightBorder(tkwin, fgGC, bgGC, hlWidth,
Tk_WindowId(tkwin));
} else {
- TkpDrawHighlightBorder(tkwin, bgGC, bgGC, hlWidth,
+ Tk_DrawHighlightBorder(tkwin, bgGC, bgGC, hlWidth,
Tk_WindowId(tkwin));
}
}
@@ -1455,6 +1520,24 @@ DisplayFrame(
return;
}
+#ifndef TK_NO_DOUBLE_BUFFERING
+ /*
+ * In order to avoid screen flashes, this function redraws the frame into
+ * off-screen memory, then copies it back on-screen in a single operation.
+ * This means there's no point in time where the on-screen image has been
+ * cleared.
+ * Also, ensure that the pixmap size is at least 1x1 pixels to prevent
+ * crashes, see [610aa08858].
+ */
+
+ pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
+ (Tk_Width(tkwin) > 0 ? Tk_Width(tkwin) : 1),
+ (Tk_Height(tkwin) > 0 ? Tk_Height(tkwin) : 1),
+ Tk_Depth(tkwin));
+#else
+ pixmap = Tk_WindowId(tkwin);
+#endif /* TK_NO_DOUBLE_BUFFERING */
+
if (framePtr->type != TYPE_LABELFRAME) {
/*
* Pass to platform specific draw function. In general, it just draws
@@ -1462,8 +1545,12 @@ DisplayFrame(
*/
noLabel:
- TkpDrawFrame(tkwin, framePtr->border, hlWidth,
+ TkpDrawFrameEx(tkwin, pixmap, framePtr->border, hlWidth,
framePtr->borderWidth, framePtr->relief);
+ if (framePtr->bgimg) {
+ DrawFrameBackground(tkwin, pixmap, hlWidth, framePtr->borderWidth,
+ framePtr->bgimg, framePtr->tile);
+ }
} else {
Labelframe *labelframePtr = (Labelframe *) framePtr;
@@ -1472,20 +1559,6 @@ DisplayFrame(
goto noLabel;
}
-#ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * In order to avoid screen flashes, this function redraws the frame
- * into off-screen memory, then copies it back on-screen in a single
- * operation. This means there's no point in time where the on-screen
- * image has been cleared.
- */
-
- pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
- Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
-#else
- pixmap = Tk_WindowId(tkwin);
-#endif /* TK_NO_DOUBLE_BUFFERING */
-
/*
* Clear the pixmap.
*/
@@ -1594,22 +1667,54 @@ DisplayFrame(
labelframePtr->labelBox.height);
}
}
+ }
#ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * Everything's been redisplayed; now copy the pixmap onto the screen
- * and free up the pixmap.
- */
+ /*
+ * Everything's been redisplayed; now copy the pixmap onto the screen and
+ * free up the pixmap.
+ */
- XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
- labelframePtr->textGC, hlWidth, hlWidth,
- (unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
- (unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
- hlWidth, hlWidth);
- Tk_FreePixmap(framePtr->display, pixmap);
+ XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
+ framePtr->copyGC, hlWidth, hlWidth,
+ (unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
+ (unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
+ hlWidth, hlWidth);
+ Tk_FreePixmap(framePtr->display, pixmap);
#endif /* TK_NO_DOUBLE_BUFFERING */
- }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawFrame --
+ *
+ * This procedure draws the rectangular frame area.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws inside the tkwin area.
+ *
+ *----------------------------------------------------------------------
+ */
+void
+TkpDrawFrame(
+ Tk_Window tkwin,
+ Tk_3DBorder border,
+ int highlightWidth,
+ int borderWidth,
+ int relief)
+{
+ /*
+ * Legacy shim to allow for external callers. Internal ones use
+ * non-exposed TkpDrawFrameEx directly so they can use double-buffering.
+ */
+
+ TkpDrawFrameEx(tkwin, Tk_WindowId(tkwin), border,
+ highlightWidth, borderWidth, relief);
}
/*
@@ -1645,7 +1750,7 @@ FrameEventProc(
goto redraw;
} else if (eventPtr->type == DestroyNotify) {
if (framePtr->menuName != NULL) {
- TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
+ Tk_SetWindowMenubar(framePtr->interp, framePtr->tkwin,
framePtr->menuName, NULL);
ckfree(framePtr->menuName);
framePtr->menuName = NULL;
@@ -1694,7 +1799,7 @@ FrameEventProc(
}
}
} else if (eventPtr->type == ActivateNotify) {
- TkpSetMainMenubar(framePtr->interp, framePtr->tkwin,
+ Tk_SetMainMenubar(framePtr->interp, framePtr->tkwin,
framePtr->menuName);
}
return;
@@ -1732,7 +1837,7 @@ FrameCmdDeletedProc(
Tk_Window tkwin = framePtr->tkwin;
if (framePtr->menuName != NULL) {
- TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
+ Tk_SetWindowMenubar(framePtr->interp, framePtr->tkwin,
framePtr->menuName, NULL);
ckfree(framePtr->menuName);
framePtr->menuName = NULL;
@@ -1929,7 +2034,7 @@ FrameRequestProc(
static void
FrameLostContentProc(
- void *clientData, /* Frame structure for content window that was
+ void *clientData, /* Frame structure for content window window that was
* stolen away. */
TCL_UNUSED(Tk_Window)) /* Tk's handle for the content window window. */
{
@@ -1964,7 +2069,7 @@ TkMapTopFrame(
framePtr->type = TYPE_TOPLEVEL;
Tcl_DoWhenIdle(MapFrame, framePtr);
if (framePtr->menuName != NULL) {
- TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin, NULL,
+ Tk_SetWindowMenubar(framePtr->interp, framePtr->tkwin, NULL,
framePtr->menuName);
}
} else if (!Tk_IsTopLevel(tkwin) && framePtr->type == TYPE_TOPLEVEL) {
@@ -2029,6 +2134,129 @@ TkToplevelWindowForCommand(
}
/*
+ *----------------------------------------------------------------------
+ *
+ * FrameBgImageProc --
+ *
+ * This function is invoked by the image code whenever the manager for an
+ * image does something that affects the size or contents of an image
+ * displayed on a frame's background.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the button to get redisplayed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+FrameBgImageProc(
+ void *clientData, /* Pointer to widget record. */
+ TCL_UNUSED(int), /* Upper left pixel (within image) that must */
+ TCL_UNUSED(int), /* be redisplayed. */
+ TCL_UNUSED(int), /* Dimensions of area to redisplay (might be */
+ TCL_UNUSED(int), /* <= 0). */
+ TCL_UNUSED(int), /* New dimensions of image. */
+ TCL_UNUSED(int))
+{
+ Frame *framePtr = (Frame *)clientData;
+
+ /*
+ * Changing the background image never alters the dimensions of the frame.
+ */
+
+ if (framePtr->tkwin && Tk_IsMapped(framePtr->tkwin) &&
+ !(framePtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayFrame, framePtr);
+ framePtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DrawFrameBackground --
+ *
+ * This function draws the background image of a rectangular frame area.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws inside the tkwin area.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+DrawFrameBackground(
+ Tk_Window tkwin,
+ Pixmap pixmap,
+ int highlightWidth,
+ int borderWidth,
+ Tk_Image bgimg,
+ int bgtile)
+{
+ int width, height; /* Area to paint on. */
+ int imageWidth, imageHeight; /* Dimensions of image. */
+ const int bw = highlightWidth + borderWidth;
+
+ Tk_SizeOfImage(bgimg, &imageWidth, &imageHeight);
+ width = Tk_Width(tkwin) - 2*bw;
+ height = Tk_Height(tkwin) - 2*bw;
+
+ if (bgtile) {
+ /*
+ * Draw the image tiled in the widget (inside the border).
+ */
+
+ int x, y;
+
+ for (x = bw; x - bw < width; x += imageWidth) {
+ int w = imageWidth;
+ if (x - bw + imageWidth > width) {
+ w = (width + bw) - x;
+ }
+ for (y = bw; y < height + bw; y += imageHeight) {
+ int h = imageHeight;
+ if (y - bw + imageHeight > height) {
+ h = (height + bw) - y;
+ }
+ Tk_RedrawImage(bgimg, 0, 0, w, h, pixmap, x, y);
+ }
+ }
+ } else {
+ /*
+ * Draw the image centred in the widget (inside the border).
+ */
+
+ int x, y, xOff, yOff, w, h;
+
+ if (width > imageWidth) {
+ x = 0;
+ xOff = (Tk_Width(tkwin) - imageWidth) / 2;
+ w = imageWidth;
+ } else {
+ x = (imageWidth - width) / 2;
+ xOff = bw;
+ w = width;
+ }
+ if (height > imageHeight) {
+ y = 0;
+ yOff = (Tk_Height(tkwin) - imageHeight) / 2;
+ h = imageHeight;
+ } else {
+ y = (imageHeight - height) / 2;
+ yOff = bw;
+ h = height;
+ }
+ Tk_RedrawImage(bgimg, x, y, w, h, pixmap, xOff, yOff);
+ }
+}
+
+/*
* Local Variables:
* mode: c
* c-basic-offset: 4