From d4f6bf9607a4aa2a4d5b1493f34c9ced59547708 Mon Sep 17 00:00:00 2001
From: jenglish <jenglish@flightlab.com>
Date: Mon, 31 May 2010 17:22:45 +0000
Subject: Tk_CreateBinding: Silently ignore empty binding scripts (Fixes [Bug
 3006842]). ttkTreeview.c: [$tv tag bind $tag <...> {}] now removes binding.

---
 ChangeLog                 |  7 +++++++
 generic/tkBind.c          |  8 ++++++--
 generic/ttk/ttkTreeview.c | 43 ++++++++++++++++++++++++-------------------
 tests/ttk/treeview.test   | 13 ++++++++++++-
 4 files changed, 49 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f29cfe2..b9040a4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2010-05-31  Joe English  <jenglish@users.sourceforge.net>
+
+	* generic/tkBind.c(Tk_CreateBinding): Silently ignore empty 
+	binding scripts (Fixes [Bug 3006842]).
+	* generic/ttk/ttkTreeview.c: [$tv tag bind $tag <...> {}]
+	now removes binding.
+
 2010-05-31  Jan Nijtmans  <nijtmans@users.sf.net>
 
 	* generic/tkMain.c:  Fix CYGWIN warning: "fd_set and assiciated.macros
diff --git a/generic/tkBind.c b/generic/tkBind.c
index ccffd9b..9bc987f 100644
--- a/generic/tkBind.c
+++ b/generic/tkBind.c
@@ -11,7 +11,7 @@
  * See the file "license.terms" for information on usage and redistribution of
  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
  *
- *  RCS: @(#) $Id: tkBind.c,v 1.45.2.3 2010/01/29 12:41:11 nijtmans Exp $
+ *  RCS: @(#) $Id: tkBind.c,v 1.45.2.4 2010/05/31 17:22:48 jenglish Exp $
  */
 
 #include "tkInt.h"
@@ -962,6 +962,10 @@ Tk_CreateBinding(
     unsigned long eventMask;
     char *newStr, *oldStr;
 
+    if (!*command) {
+	/* Silently ignore empty scripts -- see SF#3006842 */
+	return 1;
+    }
     psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString,
 	    1, 1, &eventMask);
     if (psPtr == NULL) {
@@ -1020,7 +1024,7 @@ Tk_CreateBinding(
 /*
  *---------------------------------------------------------------------------
  *
- * TkCreateBindingFunction --
+ * TkCreateBindingProcedure --
  *
  *	Add a C binding to a binding table, so that future calls to
  *	Tk_BindEvent may callback the function in the binding.
diff --git a/generic/ttk/ttkTreeview.c b/generic/ttk/ttkTreeview.c
index ad60f4b..d9f61f9 100644
--- a/generic/ttk/ttkTreeview.c
+++ b/generic/ttk/ttkTreeview.c
@@ -1,4 +1,4 @@
-/* $Id: ttkTreeview.c,v 1.23 2007/12/13 15:26:26 dgp Exp $
+/* $Id: ttkTreeview.c,v 1.23.2.1 2010/05/31 17:22:48 jenglish Exp $
  * Copyright (c) 2004, Joe English
  *
  * ttk::treeview widget implementation.
@@ -2894,6 +2894,8 @@ static int TreeviewTagBindCommand(
     Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], void *recordPtr)
 {
     Treeview *tv = recordPtr;
+    Ttk_TagTable tagTable = tv->tree.tagTable;
+    Tk_BindingTable bindingTable = tv->tree.bindingTable;
     Ttk_Tag tag;
 
     if (objc < 4 || objc > 6) {
@@ -2901,37 +2903,40 @@ static int TreeviewTagBindCommand(
 	return TCL_ERROR;
     }
 
-    tag = Ttk_GetTagFromObj(tv->tree.tagTable, objv[3]);
+    tag = Ttk_GetTagFromObj(tagTable, objv[3]);
     if (!tag) { return TCL_ERROR; }
 
     if (objc == 4) {		/* $tv tag bind $tag */
-	Tk_GetAllBindings(interp, tv->tree.bindingTable, tag);
+	Tk_GetAllBindings(interp, bindingTable, tag);
     } else if (objc == 5) { 	/* $tv tag bind $tag $sequence */
 	/* TODO: distinguish "no such binding" (OK) from "bad pattern" (ERROR)
 	 */
 	const char *script = Tk_GetBinding(interp,
-		tv->tree.bindingTable, tag, Tcl_GetString(objv[4]));
+		bindingTable, tag, Tcl_GetString(objv[4]));
 	if (script != NULL) {
 	    Tcl_SetObjResult(interp, Tcl_NewStringObj(script,-1));
 	}
     } else if (objc == 6) {	/* $tv tag bind $tag $sequence $script */
-	CONST char *sequence = Tcl_GetString(objv[4]);
-	CONST char *script = Tcl_GetString(objv[5]);
-	unsigned long mask = Tk_CreateBinding(interp,
-		tv->tree.bindingTable, tag, sequence, script, 0);
+	const char *sequence = Tcl_GetString(objv[4]);
+	const char *script = Tcl_GetString(objv[5]);
 
-	/* Test mask to make sure event is supported:
-	 */
-	if (mask & (~TreeviewBindEventMask)) {
-	    Tk_DeleteBinding(interp, tv->tree.bindingTable, tag, sequence);
-	    Tcl_ResetResult(interp);
-	    Tcl_AppendResult(interp, "unsupported event ", sequence,
-		"\nonly key, button, motion, and virtual events supported",
-		NULL);
-	    return TCL_ERROR;
+	if (!*script) { /* Delete existing binding */
+	    Tk_DeleteBinding(interp, bindingTable, tag, sequence);
+	} else {
+	    unsigned long mask = Tk_CreateBinding(interp,
+		    bindingTable, tag, sequence, script, 0);
+
+	    /* Test mask to make sure event is supported:
+	     */
+	    if (mask & (~TreeviewBindEventMask)) {
+		Tk_DeleteBinding(interp, bindingTable, tag, sequence);
+		Tcl_ResetResult(interp);
+		Tcl_AppendResult(interp, "unsupported event ", sequence,
+		    "\nonly key, button, motion, and virtual events supported",
+		    NULL);
+		return TCL_ERROR;
+	    }
 	}
-
-	return mask ? TCL_OK : TCL_ERROR;
     }
     return TCL_OK;
 }
diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test
index 46c3f6e..c97b27a 100644
--- a/tests/ttk/treeview.test
+++ b/tests/ttk/treeview.test
@@ -1,5 +1,5 @@
 #
-# $Id: treeview.test,v 1.3.2.1 2008/08/19 14:48:00 jenglish Exp $
+# $Id: treeview.test,v 1.3.2.2 2010/05/31 17:22:49 jenglish Exp $
 #
 # [7Jun2005] TO CHECK: [$tv see {}] -- shouldn't work (at least, shouldn't do
 # what it currently does)
@@ -488,4 +488,15 @@ test treeview-10.1 "Root node properly initialized (#1541739)" -setup {
     destroy .tv
 }
 
+test treeview-3006842 "Null bindings" -setup {
+    ttk::treeview .tv -show tree
+} -body {
+    .tv tag bind empty <ButtonPress-1> {}
+    .tv insert {} end -text "Click me" -tags empty
+    event generate .tv <ButtonPress-1> -x 10 -y 10
+    .tv tag bind empty
+} -result {} -cleanup {
+    destroy .tv
+}
+
 tcltest::cleanupTests
-- 
cgit v0.12