static
char
sccsid[] =
"@(#) tkFrame.c 1.59 95/06/04 14:08:47"
;
#include "default.h"
#include "tkPort.h"
#include "tkInt.h"
typedef
struct
{
Tk_Window tkwin;
Display *display;
Tcl_Interp *interp;
Tcl_Command widgetCmd;
char
*className;
int
mask;
char
*screenName;
char
*visualName;
char
*colormapName;
Colormap colormap;
Tk_3DBorder border;
int
borderWidth;
int
relief;
int
highlightWidth;
XColor *highlightBgColorPtr;
XColor *highlightColorPtr;
int
width;
int
height;
Cursor cursor;
char
*takeFocus;
int
flags;
} Frame;
#define REDRAW_PENDING 1
#define CLEAR_NEEDED 2
#define GOT_FOCUS 4
#define FRAME TK_CONFIG_USER_BIT
#define TOPLEVEL (TK_CONFIG_USER_BIT << 1)
#define BOTH (FRAME | TOPLEVEL)
static
Tk_ConfigSpec configSpecs[] = {
{TK_CONFIG_BORDER,
"-background"
,
"background"
,
"Background"
,
DEF_FRAME_BG_COLOR, Tk_Offset(Frame, border),
BOTH|TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
{TK_CONFIG_BORDER,
"-background"
,
"background"
,
"Background"
,
DEF_FRAME_BG_MONO, Tk_Offset(Frame, border),
BOTH|TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
{TK_CONFIG_SYNONYM,
"-bd"
,
"borderWidth"
, NULL,
NULL, 0, BOTH},
{TK_CONFIG_SYNONYM,
"-bg"
,
"background"
, NULL,
NULL, 0, BOTH},
{TK_CONFIG_PIXELS,
"-borderwidth"
,
"borderWidth"
,
"BorderWidth"
,
DEF_FRAME_BORDER_WIDTH, Tk_Offset(Frame, borderWidth), BOTH},
{TK_CONFIG_STRING,
"-class"
,
"class"
,
"Class"
,
DEF_FRAME_CLASS, Tk_Offset(Frame, className), FRAME},
{TK_CONFIG_STRING,
"-class"
,
"class"
,
"Class"
,
DEF_TOPLEVEL_CLASS, Tk_Offset(Frame, className), TOPLEVEL},
{TK_CONFIG_STRING,
"-colormap"
,
"colormap"
,
"Colormap"
,
DEF_FRAME_COLORMAP, Tk_Offset(Frame, colormapName),
BOTH|TK_CONFIG_NULL_OK},
{TK_CONFIG_ACTIVE_CURSOR,
"-cursor"
,
"cursor"
,
"Cursor"
,
DEF_FRAME_CURSOR, Tk_Offset(Frame, cursor), BOTH|TK_CONFIG_NULL_OK},
{TK_CONFIG_PIXELS,
"-height"
,
"height"
,
"Height"
,
DEF_FRAME_HEIGHT, Tk_Offset(Frame, height), BOTH},
{TK_CONFIG_COLOR,
"-highlightbackground"
,
"highlightBackground"
,
"HighlightBackground"
, DEF_FRAME_HIGHLIGHT_BG,
Tk_Offset(Frame, highlightBgColorPtr), BOTH},
{TK_CONFIG_COLOR,
"-highlightcolor"
,
"highlightColor"
,
"HighlightColor"
,
DEF_FRAME_HIGHLIGHT, Tk_Offset(Frame, highlightColorPtr), BOTH},
{TK_CONFIG_PIXELS,
"-highlightthickness"
,
"highlightThickness"
,
"HighlightThickness"
,
DEF_FRAME_HIGHLIGHT_WIDTH, Tk_Offset(Frame, highlightWidth), BOTH},
{TK_CONFIG_RELIEF,
"-relief"
,
"relief"
,
"Relief"
,
DEF_FRAME_RELIEF, Tk_Offset(Frame, relief), BOTH},
{TK_CONFIG_STRING,
"-screen"
,
"screen"
,
"Screen"
,
DEF_TOPLEVEL_SCREEN, Tk_Offset(Frame, screenName),
TOPLEVEL|TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING,
"-takefocus"
,
"takeFocus"
,
"TakeFocus"
,
DEF_FRAME_TAKE_FOCUS, Tk_Offset(Frame, takeFocus),
BOTH|TK_CONFIG_NULL_OK},
{TK_CONFIG_STRING,
"-visual"
,
"visual"
,
"Visual"
,
DEF_FRAME_VISUAL, Tk_Offset(Frame, visualName),
BOTH|TK_CONFIG_NULL_OK},
{TK_CONFIG_PIXELS,
"-width"
,
"width"
,
"Width"
,
DEF_FRAME_WIDTH, Tk_Offset(Frame, width), BOTH},
{TK_CONFIG_END, NULL, NULL, NULL,
NULL, 0, 0}
};
static
int
ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp,
Frame *framePtr,
int
argc, Arg *args,
int
flags));
static
void
DestroyFrame _ANSI_ARGS_((ClientData clientData));
static
void
DisplayFrame _ANSI_ARGS_((ClientData clientData));
static
void
FrameCmdDeletedProc _ANSI_ARGS_((
ClientData clientData));
static
void
FrameEventProc _ANSI_ARGS_((ClientData clientData,
XEvent *eventPtr));
static
int
FrameWidgetCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp,
int
argc, Arg *args));
static
void
MapFrame _ANSI_ARGS_((ClientData clientData));
int
Tk_FrameCmd(clientData, interp, argc, args)
ClientData clientData;
Tcl_Interp *interp;
int
argc;
Arg *args;
{
Tk_Window tkwin = (Tk_Window) clientData;
Frame *framePtr;
Tk_Window
new
= NULL;
char
*className, *screenName, *visualName, *colormapName, *arg;
int
i, c, length, toplevel, depth;
Colormap colormap;
Visual *visual;
Display *display;
if
(argc < 2) {
Tcl_AppendResult(interp,
"wrong # args: should be \""
,
LangString(args[0]),
" pathName ?options?\""
, NULL);
return
TCL_ERROR;
}
toplevel = (LangString(args[0])[0] ==
't'
);
className = colormapName = screenName = visualName = NULL;
for
(i = 2; i < argc; i += 2) {
arg = LangString(args[i]);
length =
strlen
(arg);
if
(length < 2) {
continue
;
}
c = arg[1];
if
((c ==
'c'
) && LangCmpOpt(
"-class"
,arg,
strlen
(arg)) == 0
&& (length >= 3)) {
className = LangString(args[i+1]);
}
else
if
((c ==
'c'
) && LangCmpOpt(
"-colormap"
,arg,
strlen
(arg)) == 0 ) {
colormapName = LangString(args[i+1]);
}
else
if
((c ==
's'
) && toplevel
&& (LangCmpOpt(
"-screen"
, arg,
strlen
(arg)) == 0)) {
screenName = LangString(args[i+1]);
}
else
if
((c ==
'v'
) && LangCmpOpt(
"-visual"
,arg,
strlen
(arg)) == 0 ) {
visualName = LangString(args[i+1]);
}
}
if
(screenName == NULL) {
screenName = (toplevel) ?
""
: NULL;
}
new
= Tk_CreateWindowFromPath(interp, tkwin, LangString(args[1]), screenName);
if
(
new
== NULL) {
goto
error;
}
if
(className == NULL) {
className = Tk_GetOption(
new
,
"class"
,
"Class"
);
if
(className == NULL) {
className = (toplevel) ?
"Toplevel"
:
"Frame"
;
}
}
Tk_SetClass(
new
, className);
if
(visualName == NULL) {
visualName = Tk_GetOption(
new
,
"visual"
,
"Visual"
);
}
if
(colormapName == NULL) {
colormapName = Tk_GetOption(
new
,
"colormap"
,
"Colormap"
);
}
colormap = None;
if
(visualName != NULL) {
visual = Tk_GetVisual(interp,
new
, visualName, &depth,
(colormapName == NULL) ? &colormap : (Colormap *) NULL);
if
(visual == NULL) {
goto
error;
}
Tk_SetWindowVisual(
new
, visual, depth, colormap);
}
if
(colormapName != NULL) {
colormap = Tk_GetColormap(interp,
new
, colormapName);
if
(colormap == None) {
goto
error;
}
Tk_SetWindowColormap(
new
, colormap);
}
display = Tk_Display(
new
);
framePtr = (Frame *) TkInitFrame(interp,
new
, toplevel, argc-2, args+2);
if
(framePtr == NULL) {
if
(colormap != None) {
Tk_FreeColormap(display, colormap);
}
return
TCL_ERROR;
}
framePtr->colormap = colormap;
return
TCL_OK;
error:
if
(
new
!= NULL) {
Tk_DestroyWindow(
new
);
}
return
TCL_ERROR;
}
char
*
TkInitFrame(interp, tkwin, toplevel, argc, args)
Tcl_Interp *interp;
Tk_Window tkwin;
int
toplevel;
int
argc;
Arg *args;
{
register
Frame *framePtr;
framePtr = (Frame *) ckalloc(
sizeof
(Frame));
framePtr->tkwin = tkwin;
framePtr->display = Tk_Display(tkwin);
framePtr->interp = interp;
framePtr->widgetCmd = Lang_CreateWidget(interp,framePtr->tkwin, FrameWidgetCmd, (ClientData) framePtr, FrameCmdDeletedProc);
framePtr->className = NULL;
framePtr->mask = (toplevel) ? TOPLEVEL : FRAME;
framePtr->screenName = NULL;
framePtr->visualName = NULL;
framePtr->colormapName = NULL;
framePtr->colormap = None;
framePtr->border = NULL;
framePtr->borderWidth = 0;
framePtr->relief = TK_RELIEF_FLAT;
framePtr->highlightWidth = 0;
framePtr->highlightBgColorPtr = NULL;
framePtr->highlightColorPtr = NULL;
framePtr->width = 0;
framePtr->height = 0;
framePtr->cursor = None;
framePtr->takeFocus = NULL;
framePtr->flags = 0;
Tk_CreateEventHandler(framePtr->tkwin,
ExposureMask|StructureNotifyMask|FocusChangeMask,
FrameEventProc, (ClientData) framePtr);
if
(ConfigureFrame(interp, framePtr, argc, args, 0) != TCL_OK) {
Tk_DestroyWindow(framePtr->tkwin);
return
NULL;
}
if
(toplevel) {
Tk_DoWhenIdle(MapFrame, (ClientData) framePtr);
}
Tcl_ArgResult(interp,LangWidgetArg(interp,framePtr->tkwin));
return
(
char
*) framePtr;
}
static
int
FrameWidgetCmd(clientData, interp, argc, args)
ClientData clientData;
Tcl_Interp *interp;
int
argc;
Arg *args;
{
register
Frame *framePtr = (Frame *) clientData;
int
result = TCL_OK;
size_t
length;
int
c, i;
if
(argc < 2) {
Tcl_AppendResult(interp,
"wrong # args: should be \""
,
LangString(args[0]),
" option ?arg arg ...?\""
, NULL);
return
TCL_ERROR;
}
Tk_Preserve((ClientData) framePtr);
c = LangString(args[1])[0];
length =
strlen
(LangString(args[1]));
if
((c ==
'c'
) && (
strncmp
(LangString(args[1]),
"cget"
, length) == 0)
&& (length >= 2)) {
if
(argc != 3) {
Tcl_AppendResult(interp,
"wrong # args: should be \""
,
LangString(args[0]),
" cget option\""
,
NULL);
result = TCL_ERROR;
goto
done;
}
result = Tk_ConfigureValue(interp, framePtr->tkwin, configSpecs,
(
char
*) framePtr, LangString(args[2]), framePtr->mask);
}
else
if
((c ==
'c'
) && (
strncmp
(LangString(args[1]),
"configure"
, length) == 0)
&& (length >= 2)) {
if
(argc == 2) {
result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
(
char
*) framePtr, NULL, framePtr->mask);
}
else
if
(argc == 3) {
result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
(
char
*) framePtr, LangString(args[2]), framePtr->mask);
}
else
{
for
(i = 2; i < argc; i++) {
length =
strlen
(LangString(args[i]));
if
(length < 2) {
continue
;
}
c = LangString(args[i])[1];
if
(((c ==
'c'
) && LangCmpOpt(
"-class"
,LangString(args[i]),length) == 0
&& (length >= 2))
|| ((c ==
'c'
) && (framePtr->mask == TOPLEVEL)
&& (LangCmpOpt(
"-colormap"
, LangString(args[i]), length) == 0))
|| ((c ==
's'
) && (framePtr->mask == TOPLEVEL)
&& (LangCmpOpt(
"-screen"
, LangString(args[i]), length) == 0))
|| ((c ==
'v'
) && (framePtr->mask == TOPLEVEL)
&& (LangCmpOpt(
"-visual"
, LangString(args[i]), length) == 0))) {
Tcl_AppendResult(interp,
"can't modify "
, LangString(args[i]),
" option after widget is created"
, NULL);
result = TCL_ERROR;
goto
done;
}
}
result = ConfigureFrame(interp, framePtr, argc-2, args+2,
TK_CONFIG_ARGV_ONLY);
}
}
else
{
Tcl_AppendResult(interp,
"bad option \""
, LangString(args[1]),
"\": must be cget or configure"
, NULL);
result = TCL_ERROR;
}
done:
Tk_Release((ClientData) framePtr);
return
result;
}
static
void
DestroyFrame(clientData)
ClientData clientData;
{
register
Frame *framePtr = (Frame *) clientData;
Tk_FreeOptions(configSpecs, (
char
*) framePtr, framePtr->display,
framePtr->mask);
if
(framePtr->colormap != None) {
Tk_FreeColormap(framePtr->display, framePtr->colormap);
}
ckfree((
char
*) framePtr);
}
static
int
ConfigureFrame(interp, framePtr, argc, args, flags)
Tcl_Interp *interp;
register
Frame *framePtr;
int
argc;
Arg *args;
int
flags;
{
if
(Tk_ConfigureWidget(interp, framePtr->tkwin, configSpecs,
argc, args, (
char
*) framePtr, flags | framePtr->mask) != TCL_OK) {
return
TCL_ERROR;
}
if
(framePtr->border != NULL) {
Tk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);
}
if
(framePtr->highlightWidth < 0) {
framePtr->highlightWidth = 0;
}
Tk_SetInternalBorder(framePtr->tkwin,
framePtr->borderWidth + framePtr->highlightWidth);
if
((framePtr->width > 0) || (framePtr->height > 0)) {
Tk_GeometryRequest(framePtr->tkwin, framePtr->width,
framePtr->height);
}
if
(Tk_IsMapped(framePtr->tkwin)) {
if
(!(framePtr->flags & REDRAW_PENDING)) {
Tk_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
}
framePtr->flags |= REDRAW_PENDING|CLEAR_NEEDED;
}
return
TCL_OK;
}
static
void
DisplayFrame(clientData)
ClientData clientData;
{
register
Frame *framePtr = (Frame *) clientData;
register
Tk_Window tkwin = framePtr->tkwin;
GC gc;
framePtr->flags &= ~REDRAW_PENDING;
if
((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
return
;
}
if
(framePtr->flags & CLEAR_NEEDED) {
XClearWindow(framePtr->display, Tk_WindowId(tkwin));
framePtr->flags &= ~CLEAR_NEEDED;
}
if
((framePtr->border != NULL)
&& (framePtr->relief != TK_RELIEF_FLAT)) {
Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin),
framePtr->border, framePtr->highlightWidth,
framePtr->highlightWidth,
Tk_Width(tkwin) - 2*framePtr->highlightWidth,
Tk_Height(tkwin) - 2*framePtr->highlightWidth,
framePtr->borderWidth, framePtr->relief);
}
if
(framePtr->highlightWidth != 0) {
if
(framePtr->flags & GOT_FOCUS) {
gc = Tk_GCForColor(framePtr->highlightColorPtr,
Tk_WindowId(tkwin));
}
else
{
gc = Tk_GCForColor(framePtr->highlightBgColorPtr,
Tk_WindowId(tkwin));
}
Tk_DrawFocusHighlight(tkwin, gc, framePtr->highlightWidth,
Tk_WindowId(tkwin));
}
}
static
void
FrameEventProc(clientData, eventPtr)
ClientData clientData;
register
XEvent *eventPtr;
{
register
Frame *framePtr = (Frame *) clientData;
if
((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
goto
redraw;
}
else
if
(eventPtr->type == ConfigureNotify) {
framePtr->flags |= CLEAR_NEEDED;
goto
redraw;
}
else
if
(eventPtr->type == DestroyNotify) {
if
(framePtr->tkwin != NULL) {
framePtr->tkwin = NULL;
Lang_DeleteWidget(framePtr->interp,framePtr->widgetCmd);
}
if
(framePtr->flags & REDRAW_PENDING) {
Tk_CancelIdleCall(DisplayFrame, (ClientData) framePtr);
}
Tk_CancelIdleCall(MapFrame, (ClientData) framePtr);
Tk_EventuallyFree((ClientData) framePtr, DestroyFrame);
}
else
if
(eventPtr->type == FocusIn) {
if
(eventPtr->xfocus.detail != NotifyInferior) {
framePtr->flags |= GOT_FOCUS;
if
(framePtr->highlightWidth > 0) {
goto
redraw;
}
}
}
else
if
(eventPtr->type == FocusOut) {
if
(eventPtr->xfocus.detail != NotifyInferior) {
framePtr->flags &= ~GOT_FOCUS;
if
(framePtr->highlightWidth > 0) {
goto
redraw;
}
}
}
return
;
redraw:
if
((framePtr->tkwin != NULL) && !(framePtr->flags & REDRAW_PENDING)) {
Tk_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
framePtr->flags |= REDRAW_PENDING;
}
}
static
void
FrameCmdDeletedProc(clientData)
ClientData clientData;
{
Frame *framePtr = (Frame *) clientData;
Tk_Window tkwin = framePtr->tkwin;
if
(tkwin != NULL) {
framePtr->tkwin = NULL;
Tk_DestroyWindow(tkwin);
}
}
static
void
MapFrame(clientData)
ClientData clientData;
{
Frame *framePtr = (Frame *) clientData;
Tk_Preserve((ClientData) framePtr);
while
(1) {
if
(Tk_DoOneEvent(TK_IDLE_EVENTS) == 0) {
break
;
}
if
(framePtr->tkwin == NULL) {
Tk_Release((ClientData) framePtr);
return
;
}
}
Tk_MapWindow(framePtr->tkwin);
Tk_Release((ClientData) framePtr);
}