TIP 647: Change Tk_ConfigureWidgets signature, abandon TK_CONFIG_OBJS

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Author:		Jan Nijtmans <jan.nijtmans@gmail.com>
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 its 4th and 5th argument were kept as argc/argv, although they could be objc/objv as well.

Now that Tk 9.0 is approaching, the Tk_ConfigureWidgets() signature can be corrected to be 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 make it possible 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. It's not worth maintaining this for a long time more: The one-time effort of converting the extensions is fully worth the trouble, and after the suggested conversion, everything still works with Tk 8.6 as well.

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 usage of the flag TK_CONFIG_OBJS in Tk is removed, assuming that the flag is set.

In addition, the alwaysRedraw field in Tk_ItemType is renamed to flags. Currently it contains two different flags, TK_ALWAYS_REDRAW and TK_MOVABLE_POINTS. For compatibility, TK_ALWAYS_REDRAW has the value 1. This field also contains the TK_CONFIG_OBJS flag, but that flag is now obsolete. The flag TK_MOVABLE_POINTS is not new: It was contained in the alwaysRedraw field was. 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 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;
    }

That is, the typecast for objv is changed to (void *). This way compiles and runs fine with both Tk 8.6 and 9.0.

Code which does not yet use the TK_CONFIG_OBJS flag must be modified to no-longer use the argv/argc functions, and instead switch to using the objc/objv concept. This becomes clear when compiling such extensions with Tk 9 header files: The signature change causes a compiler warning if the conversion is not yet done.

Tkimg is already converted this way, and it compiles 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 easy to port to this signature change. Other extensions (like blt, snack, tkhtml, tkled, tknotebook, tkpath and tktable) 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.

History