Tk Source Code

Changes On Branch bug-e6140f3404
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch bug-e6140f3404 Excluding Merge-Ins

This is equivalent to a diff from 045281bc to a37038ac

2024-06-03
06:12
Fix [e6140f3404]: Crashes in empty ttk::panedwindowfor pane and forget commands (and a bugfix in ttk::notebook tab insert command while passing by). check-in: fbbf1940 user: fvogel tags: trunk, main
2024-06-02
19:41
Fix issue preventing notebook-9.2 from passing. Closed-Leaf check-in: a37038ac user: fvogel tags: bug-e6140f3404
17:17
Add tests notebook-9.1 and notebook-9.2. notebook-9.1 passes in this branch (but not in current trunk). notebook-9.2 fails, even in this branch. check-in: 4a45ebfd user: fvogel tags: bug-e6140f3404
07:15
Fix [0fb337ea84]: ttk::combobox selection overruns downarrow element. Thanks to Emiliano Gavilan. check-in: 32adda38 user: fvogel tags: trunk, main
2024-06-01
17:07
New branch implementing Christopher Chavez's idea for drawing to a CGImage without using drawRect. This is for Tk9 check-in: 13d71ae7 user: culler tags: cgimage_drawing_tk9
11:16
Change Ttk_GetContentIndexFromObj API to take an additional parameter indicating whether end+1 indices are allowed. check-in: f6d94f47 user: apnadkarni tags: bug-e6140f3404
2024-05-29
20:16
Merge-mark check-in: 045281bc user: jan.nijtmans tags: trunk, main
20:11
Merge 8.6 check-in: c97bea36 user: jan.nijtmans tags: core-8-branch
18:46
Merge core-8-6-branch. check-in: 7dc8ff8b user: fvogel tags: trunk, main

Changes to generic/ttk/ttkManager.c.
430
431
432
433
434
435
436
437
438
439
440




441
442
443
444
445
446
447
448
449
450
451
452
453
454
455





456
457
458
459
460
461
462
463
    Tcl_Size index;
    for (index = 0; index < mgr->nContent; ++index)
	if (mgr->content[index]->window == window)
	    return index;
    return -1;
}

/* ++ Ttk_GetContentIndexFromObj(interp, mgr, objPtr, indexPtr) --
 * 	Return the index of the content window specified by objPtr.
 * 	Content windows may be specified as an integer index or
 * 	as the name of the managed window.




 *
 * Returns:
 * 	Standard Tcl completion code.  Leaves an error message in case of error.
 */

int Ttk_GetContentIndexFromObj(
    Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, Tcl_Size *indexPtr)
{
    const char *string = Tcl_GetString(objPtr);
    Tcl_Size index = 0;
    Tk_Window tkwin;

    /* Try interpreting as an integer first:
     */
    if (TkGetIntForIndex(objPtr, mgr->nContent - 1, 1, &index) == TCL_OK) {





	if (index < 0 || index > mgr->nContent) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Managed window index %d out of bounds", (int)index));
	    Tcl_SetErrorCode(interp, "TTK", "MANAGED", "INDEX", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = index;
	return TCL_OK;







|



>
>
>
>






|







|
>
>
>
>
>
|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    Tcl_Size index;
    for (index = 0; index < mgr->nContent; ++index)
	if (mgr->content[index]->window == window)
	    return index;
    return -1;
}

/* ++ Ttk_GetContentIndexFromObj(interp, mgr, objPtr, lastOK, indexPtr) --
 * 	Return the index of the content window specified by objPtr.
 * 	Content windows may be specified as an integer index or
 * 	as the name of the managed window.
 *
 *  The parameter lastOK should be non-0 if the resolved index can be equal to
 *  the current size (i.e. one more than the current highest index) and 0
 *  otherwise.
 *
 * Returns:
 * 	Standard Tcl completion code.  Leaves an error message in case of error.
 */

int Ttk_GetContentIndexFromObj(
    Tcl_Interp *interp, Ttk_Manager *mgr, Tcl_Obj *objPtr, int lastOK, Tcl_Size *indexPtr)
{
    const char *string = Tcl_GetString(objPtr);
    Tcl_Size index = 0;
    Tk_Window tkwin;

    /* Try interpreting as an integer first:
     */
    if (TkGetIntForIndex(objPtr, mgr->nContent - 1, lastOK, &index) == TCL_OK) {
	/*
	 * Note despite passing lastOK above, we still need to check here
	 * as well as TkGetIntForIndex only uses lastOK for end-relative indices,
	 * not integers.
	 */
	if (index < 0 || (index - !!lastOK) >= mgr->nContent) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Managed window index %d out of bounds", (int)index));
	    Tcl_SetErrorCode(interp, "TTK", "MANAGED", "INDEX", NULL);
	    return TCL_ERROR;
	}
	*indexPtr = index;
	return TCL_OK;
Changes to generic/ttk/ttkManager.h.
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 */
#define Ttk_SlaveIndex Ttk_ContentIndex
MODULE_SCOPE Tcl_Size Ttk_ContentIndex(Ttk_Manager *, Tk_Window);
    /* Returns: index in content array of specified window, TCL_INDEX_NONE if not found */

#define Ttk_GetSlaveIndexFromObj Ttk_GetContentIndexFromObj
MODULE_SCOPE int Ttk_GetContentIndexFromObj(
    Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, Tcl_Size *indexPtr);

/* Accessor functions:
 */
#define Ttk_NumberSlaves Ttk_NumberContent
MODULE_SCOPE Tcl_Size Ttk_NumberContent(Ttk_Manager *);
    /* Returns: number of managed content windows */








|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 */
#define Ttk_SlaveIndex Ttk_ContentIndex
MODULE_SCOPE Tcl_Size Ttk_ContentIndex(Ttk_Manager *, Tk_Window);
    /* Returns: index in content array of specified window, TCL_INDEX_NONE if not found */

#define Ttk_GetSlaveIndexFromObj Ttk_GetContentIndexFromObj
MODULE_SCOPE int Ttk_GetContentIndexFromObj(
    Tcl_Interp *, Ttk_Manager *, Tcl_Obj *, int lastOK, Tcl_Size *indexPtr);

/* Accessor functions:
 */
#define Ttk_NumberSlaves Ttk_NumberContent
MODULE_SCOPE Tcl_Size Ttk_NumberContent(Ttk_Manager *);
    /* Returns: number of managed content windows */

Changes to generic/ttk/ttkNotebook.c.
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
	*index_rtn = nb->notebook.currentIndex;
	return TCL_OK;
    }

    /* ... or integer index or content window name:
     */
    if (Ttk_GetContentIndexFromObj(
	    interp, nb->notebook.mgr, objPtr, index_rtn) == TCL_OK)
    {
	return TCL_OK;
    }
    if (*index_rtn == Ttk_NumberContent(nb->notebook.mgr)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Invalid tab specification %s", string));
	Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "SPEC", NULL);







|







859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
	*index_rtn = nb->notebook.currentIndex;
	return TCL_OK;
    }

    /* ... or integer index or content window name:
     */
    if (Ttk_GetContentIndexFromObj(
	    interp, nb->notebook.mgr, objPtr, 1, index_rtn) == TCL_OK)
    {
	return TCL_OK;
    }
    if (*index_rtn == Ttk_NumberContent(nb->notebook.mgr)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"Invalid tab specification %s", string));
	Tcl_SetErrorCode(interp, "TTK", "NOTEBOOK", "SPEC", NULL);
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981




982
983
984
985
986
987
988
989
990





991
992
993
994
995
996
997
    Tcl_Size srcIndex, destIndex;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2,objv, "index window ?-option value ...?");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[2], &destIndex)) {
	return TCL_ERROR;
    }

    if (Tcl_GetString(objv[3])[0] == '.') {
	/* Window name -- could be new or existing content window.
	 */
	Tk_Window window =
	    Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin);

	if (!window) {
	    return TCL_ERROR;
	}

	srcIndex = Ttk_ContentIndex(nb->notebook.mgr, window);
	if (srcIndex < 0) {	/* New content window */




	    return AddTab(interp, nb, destIndex, window, objc-4,objv+4);
	}
    } else if (Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[3], &srcIndex) != TCL_OK)
    {
	return TCL_ERROR;
    } else if (srcIndex  >= Ttk_NumberContent(nb->notebook.mgr)) {
	srcIndex = Ttk_NumberContent(nb->notebook.mgr) - 1;
    }






    /* Move existing content window:
     */
    if (ConfigureTab(interp, nb,
	     (Tab *)Ttk_ContentData(nb->notebook.mgr, srcIndex),
		 Ttk_ContentWindow(nb->notebook.mgr, srcIndex),
	     objc-4,objv+4) != TCL_OK)







<
<
<
<
<












>
>
>
>



|





>
>
>
>
>







958
959
960
961
962
963
964





965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
    Tcl_Size srcIndex, destIndex;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 2,objv, "index window ?-option value ...?");
	return TCL_ERROR;
    }






    if (Tcl_GetString(objv[3])[0] == '.') {
	/* Window name -- could be new or existing content window.
	 */
	Tk_Window window =
	    Tk_NameToWindow(interp,Tcl_GetString(objv[3]),nb->core.tkwin);

	if (!window) {
	    return TCL_ERROR;
	}

	srcIndex = Ttk_ContentIndex(nb->notebook.mgr, window);
	if (srcIndex < 0) {	/* New content window */
	    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[2], 1, &destIndex)) {
		return TCL_ERROR;
	    }
	    return AddTab(interp, nb, destIndex, window, objc-4,objv+4);
	}
    } else if (Ttk_GetContentIndexFromObj(
		interp, nb->notebook.mgr, objv[3], 0, &srcIndex) != TCL_OK)
    {
	return TCL_ERROR;
    } else if (srcIndex  >= Ttk_NumberContent(nb->notebook.mgr)) {
	srcIndex = Ttk_NumberContent(nb->notebook.mgr) - 1;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
	interp, nb->notebook.mgr, objv[2], 0, &destIndex)) {
	return TCL_ERROR;
    }

    /* Move existing content window:
     */
    if (ConfigureTab(interp, nb,
	     (Tab *)Ttk_ContentData(nb->notebook.mgr, srcIndex),
		 Ttk_ContentWindow(nb->notebook.mgr, srcIndex),
	     objc-4,objv+4) != TCL_OK)
Changes to generic/ttk/ttkPanedwindow.c.
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
    window = Tk_NameToWindow(
	interp, Tcl_GetString(objv[3]), pw->core.tkwin);
    if (!window) {
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp,pw->paned.mgr, objv[2], &destIndex))
    {
	return TCL_ERROR;
    }

    srcIndex = Ttk_ContentIndex(pw->paned.mgr, window);
    if (srcIndex < 0) { /* New content: */
	return AddPane(interp, pw, destIndex, window, objc-4, objv+4);







|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
    window = Tk_NameToWindow(
	interp, Tcl_GetString(objv[3]), pw->core.tkwin);
    if (!window) {
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		interp,pw->paned.mgr, objv[2], 1, &destIndex))
    {
	return TCL_ERROR;
    }

    srcIndex = Ttk_ContentIndex(pw->paned.mgr, window);
    if (srcIndex < 0) { /* New content: */
	return AddPane(interp, pw, destIndex, window, objc-4, objv+4);
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp, pw->paned.mgr, objv[2], &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }
    Ttk_ForgetContent(pw->paned.mgr, paneIndex);








|







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp, pw->paned.mgr, objv[2], 0, &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }
    Ttk_ForgetContent(pw->paned.mgr, paneIndex);

779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp,pw->paned.mgr, objv[2], &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }

    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, paneIndex);







|







779
780
781
782
783
784
785
786
787
788
789
790
791
792
793

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 2,objv, "pane ?-option value ...?");
	return TCL_ERROR;
    }

    if (TCL_OK != Ttk_GetContentIndexFromObj(
		    interp,pw->paned.mgr, objv[2], 0, &paneIndex))
    {
	return TCL_ERROR;
    } else if (paneIndex >= Ttk_NumberContent(pw->paned.mgr)) {
	paneIndex = Ttk_NumberContent(pw->paned.mgr) - 1;
    }

    pane = (Pane *)Ttk_ContentData(pw->paned.mgr, paneIndex);
Changes to tests/ttk/notebook.test.
549
550
551
552
553
554
555























556
    ttk::style configure customStyle.TNotebook
    ttk::notebook .w -style customStyle.TNotebook
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TNotebook customStyle.TNotebook TNotebook}
























tcltest::cleanupTests







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
    ttk::style configure customStyle.TNotebook
    ttk::notebook .w -style customStyle.TNotebook
    list [.w cget -style] [.w style] [winfo class .w]
} -cleanup {
    destroy .w
} -result {customStyle.TNotebook customStyle.TNotebook TNotebook}

test notebook-9.1 "move last tab by numerical index" -body {
    ::ttk::notebook .n
    foreach tabs {TabA TabB TabC} {
	::ttk::entry .n.[string tolower $tabs]
	.n add .n.[string tolower $tabs] -text $tabs
    }
   .n insert 0 2  ; # allowed: TabC moves to first tab position
   .n insert 0 3  ; # not allowed: position 3 is after last tab
} -cleanup {
    destroy .n
} -result {Managed window index 3 out of bounds} -returnCodes error
test notebook-9.2 "move first tab to last position by numerical index" -body {
    ::ttk::notebook .n
    foreach tabs {TabA TabB TabC} {
	::ttk::entry .n.[string tolower $tabs]
	.n add .n.[string tolower $tabs] -text $tabs
    }
   .n insert 2 0  ; # allowed: TabA moves to last tab position
   .n insert 3 0  ; # not allowed: position 3 is after last tab
} -cleanup {
    destroy .n
} -result {Managed window index 3 out of bounds} -returnCodes error

tcltest::cleanupTests
Changes to tests/ttk/panedwindow.test.
1
2
3
4
5
6
7
8
9
10
11
12
















13
14
15
16
17
18
19
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

proc propagate-geometry {} { update idletasks }

# Basic sanity checks:
#
test panedwindow-1.0 "Setup" -body {
    ttk::panedwindow .pw
} -result .pw

















test panedwindow-1.1 "Make sure empty panedwindow doesn't crash" -body {
    pack .pw -expand true -fill both
    update
}

test panedwindow-1.2 "Add a pane" -body {












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package require tk
package require tcltest 2.2
namespace import -force tcltest::*
loadTestedCommands

proc propagate-geometry {} { update idletasks }

# Basic sanity checks:
#
test panedwindow-1.0 "Setup" -body {
    ttk::panedwindow .pw
} -result .pw

test panedwindow-1.0.1 "Make sure pane 0 command doesn't crash on empty pane - bug e6140f3404" -body {
    .pw pane 0
} -result {Managed window index 0 out of bounds} -returnCodes error

test panedwindow-1.0.2 "Make sure pane end command doesn't crash on empty pane - bug e6140f3404" -body {
    .pw pane end
} -result {Managed window index -1 out of bounds} -returnCodes error

test panedwindow-1.0.3 "Make sure forget 0 command doesn't crash on empty pane - bug e6140f3404" -body {
    .pw forget 0
} -result {Managed window index 0 out of bounds} -returnCodes error

test panedwindow-1.0.4 "Make sure forget end command doesn't crash on empty pane - bug e6140f3404" -body {
    .pw forget end
} -result {Managed window index -1 out of bounds} -returnCodes error

test panedwindow-1.1 "Make sure empty panedwindow doesn't crash" -body {
    pack .pw -expand true -fill both
    update
}

test panedwindow-1.2 "Add a pane" -body {