TIP 647: Change Tk_ConfigureWidgets signature, abandon TK_CONFIG_OBJS

Login
Author:		Jan Nijtmans <[email protected]>
State:		Final
Type:		Project
Vote:		Done
Created:	04-11-2022
Tcl-Version:	9.0
Tk-branch:	tip-647
Vote-Summary:	4 / 0 / 0
Votes-For:	BG, DKF, JN, SL
Votes-Against:	none
Votes-Present:	none

Abstract

In december 1999, the TK_CONFIG_OBJS flag was introduced in Tk, making it possible to use the Tcl_Obj-interface in a lot more places than before (e.g. the canvas) . Since this was Tk 8.1, the signature of the Tk_ConfigureWidgets() function could not be changed, therefore it's 4th and 5th argument were kept as argc/argv, although they could be objc/objv as well.

Now that Tk 9.0 is approaching, we can correct the Tk_ConfigureWidgets() signature as it should have been from the beginning, and also remove the possibility to use argc/argv any more.

Background & Rationale

The function Tk_ConfigureWidget is typically used like this:

    if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
	    objc, (const char **)objv, (char *)canvasPtr,
	    flags|TK_CONFIG_OBJS) != TCL_OK) {
	return TCL_ERROR;
    }
The goal of this TIP is to allow to get rid of the type-casts and the TK_CONFIG_OBJS flag in Tk 9.0:
    if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
	    objc, objv, canvasPtr, flags) != TCL_OK) {
	return TCL_ERROR;
    }

This can be done by changing the 5th argument in the function signature from const char ** to Tcl_Obj *const * and the 6th argument to void *.

Of course it would be possible to keep the TK_CONFIG_OBJS flag. In my view it's not really worth maintaining this for a long time more: the one-time effort converting the extensions is fully worth the trouble. And after the suggested conversion, everything still works with Tk 8.6 too.

Specification

The signature of the function is modified from:

    int Tk_ConfigureWidget(Tcl_Interp *interp,
	    Tk_Window tkwin, const Tk_ConfigSpec *specs,
	    Tcl_Size argc, const char **argv, char *widgRec,
	    int flags)
to
    int Tk_ConfigureWidget(Tcl_Interp *interp,
	    Tk_Window tkwin, const Tk_ConfigSpec *specs,
	    Tcl_Size objc, Tcl_Obj *const *objv, void *widgRec,
	    int flags)

Also, all usages of the flag TK_CONFIG_OBJS in Tk are removed, assuming that the flag is set.

In addition, the alwaysRedraw field in Tk_ItemType will be renamed to flags. Currently it can contains two different flags, TK_ALWAYS_REDRAW and TK_MOVABLE_POINTS. For compatibility, TK_ALWAYS_REDRAW has the value 1. This field also located the TK_CONFIG_OBJS flag, but that flags becomes obsolete now. The flag TK_MOVABLE_POINTS is not new, the alwaysRedraw field was where this flag had to be set (and exactly this is the motivation for the suggestion to change the field name).

Since the Tk_ItemType is generally statically initialized, the field name change doesn't need any user code modification: All extensions using it will work unmodified.

Compatibility

For code which needs to work with both Tk 8.6 and 9.0, the following construct can be used:

    if (Tk_ConfigureWidget(interp, canvasPtr->tkwin, configSpecs,
	    objc, (void *)objv, (char *)canvasPtr,
	    flags|TK_CONFIG_OBJS) != TCL_OK) {
	return TCL_ERROR;
    }
So just change the typecast for objv to (void *), this way will compile and run fine with both Tk 8.6 and 9.0.

Code which still is not using the TK_CONFIG_OBJS flag will need to be modified: No longer use the argv/argc functions but switch to using the objc/objv concept. This will become clear when compiling such extensions with Tk 9 header files: The signature change will cause a compiler warning if the conversion is not yet done.

Tkimg is already converted this way. It will still compile fine after this TIP is accepted. The Tkimg conversion commit can be found here

Some extensions (like vu Widget Set and tkzinc) are already modified to use the TK_CONFIG_OBJS flag, those are quite easy to be ported to this signature change. Other extensions (like blt, snack, tkhtml, tkled, tknotebook, tkpath and tktable) will need more work, because the already-mentioned argc/argv->objc/objv conversion needs to be done first.

Implementation

Implementation is available in the tip-647 branch of the Tk repository.

Copyright

This document has been placed in the public domain.