summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/CrtSelHdlr.313
-rw-r--r--generic/tkSelect.c78
-rw-r--r--tests/clipboard.test4
-rw-r--r--tests/select.test2
4 files changed, 66 insertions, 31 deletions
diff --git a/doc/CrtSelHdlr.3 b/doc/CrtSelHdlr.3
index b7758df..9e8c1f2 100644
--- a/doc/CrtSelHdlr.3
+++ b/doc/CrtSelHdlr.3
@@ -109,8 +109,19 @@ If \fBTk_CreateSelHandler\fR is called when there already exists a
handler for \fIselection\fR and \fItarget\fR on \fItkwin\fR, then the
existing handler is replaced with a new one.
.PP
+When \fBTk_CreateSelHandler\fR is called with a \fItarget\fR argument
+of STRING, Tk automatically creates a second handler with \fItarget\fR
+and \fIformat\fR set to UTF8_STRING. If a UTF8_STRING handler already
+exists for \fIselection\fR on \fItkwin\fR, it is replaced, unless an
+existing STRING handler is also being replaced that has a different
+\fIproc\fR than the existing UTF8_STRING handler.
+.PP
\fBTk_DeleteSelHandler\fR removes the handler given by \fItkwin\fR,
\fIselection\fR, and \fItarget\fR, if such a handler exists.
-If there is no such handler then it has no effect.
+If there is no such handler then it has no effect. If
+\fBTk_DeleteSelHandler\fR successfully removes a handler with a
+\fItarget\fR of STRING, it also attempts to remove a corresponding
+handler with \fItarget\fR and \fIformat\fR equal to UTF8_STRING and
+the same values of \fItkwin\fR and \fIproc\fR as the STRING handler.
.SH KEYWORDS
format, handler, selection, target
diff --git a/generic/tkSelect.c b/generic/tkSelect.c
index 2414b3d..a078e1b 100644
--- a/generic/tkSelect.c
+++ b/generic/tkSelect.c
@@ -127,6 +127,7 @@ Tk_CreateSelHandler(
{
register TkSelHandler *selPtr;
TkWindow *winPtr = (TkWindow *) tkwin;
+ Tk_SelectionProc *oldProc;
if (winPtr->dispPtr->multipleAtom == None) {
TkSelInit(tkwin);
@@ -142,10 +143,24 @@ Tk_CreateSelHandler(
selPtr = ckalloc(sizeof(TkSelHandler));
selPtr->nextPtr = winPtr->selHandlerList;
winPtr->selHandlerList = selPtr;
+
+ /*
+ * When creating a new handler, we set the old proc to zero which
+ * compares unequal to any real Tk selection handler entry.
+ */
+
+ oldProc = NULL;
break;
}
if ((selPtr->selection == selection) && (selPtr->target == target)) {
/*
+ * When replacing an existing handler, we remember the previous
+ * proc for later comparison with the UTF8_STRING handler.
+ */
+
+ oldProc = selPtr->proc;
+
+ /*
* Special case: when replacing handler created by "selection
* handle", free up memory. Should there be a callback to allow
* other clients to do this too?
@@ -172,42 +187,51 @@ Tk_CreateSelHandler(
/*
* If the user asked for a STRING handler and we understand
* UTF8_STRING, we implicitly create a UTF8_STRING handler for them.
+ * First we check if a UTF8_STRING handler already exists for the same
+ * widget and selection. If one doesn't exist, one must be created.
+ * If one does exist and it has the same proc as the STRING handler
+ * that we just replaced, it must also be replaced. If one does exist
+ * but it has a different proc, or if we didn't just replace an
+ * existing STRING handler, we must leave it alone, since we didn't
+ * automatically create it in the first place.
*/
+ TkSelHandler *utf8selPtr;
+
target = winPtr->dispPtr->utf8Atom;
- for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
- if (selPtr == NULL) {
- selPtr = ckalloc(sizeof(TkSelHandler));
- selPtr->nextPtr = winPtr->selHandlerList;
- winPtr->selHandlerList = selPtr;
- selPtr->selection = selection;
- selPtr->target = target;
- selPtr->format = target; /* We want UTF8_STRING format */
- selPtr->proc = proc;
- if (selPtr->proc == HandleTclCommand) {
- /*
- * The clientData is selection controlled memory, so we
- * should make a copy for this selPtr.
- */
-
- unsigned cmdInfoLen = Tk_Offset(CommandInfo, command) +
- ((CommandInfo *)clientData)->cmdLength + 1;
-
- selPtr->clientData = ckalloc(cmdInfoLen);
- memcpy(selPtr->clientData, clientData, cmdInfoLen);
- } else {
- selPtr->clientData = clientData;
- }
- selPtr->size = 8;
+ for (utf8selPtr = winPtr->selHandlerList; utf8selPtr != NULL;
+ utf8selPtr = utf8selPtr->nextPtr) {
+ if ((utf8selPtr->selection == selection)
+ && (utf8selPtr->target == target)) {
break;
}
- if (selPtr->selection==selection && selPtr->target==target) {
+ }
+ if (utf8selPtr == NULL || ((utf8selPtr->format == target)
+ && (utf8selPtr->proc == oldProc))) {
+ ClientData newClientData;
+
+ if (proc == HandleTclCommand) {
/*
- * Looks like we had a utf-8 target already. Leave it alone.
+ * The clientData is selection controlled memory, so we should
+ * make a copy for this new selection handler.
*/
- break;
+ unsigned cmdInfoLen = sizeof(CommandInfo) +
+ ((CommandInfo*)clientData)->cmdLength - 3;
+
+ newClientData = (ClientData) ckalloc(cmdInfoLen);
+ memcpy(newClientData, clientData, cmdInfoLen);
+ } else {
+ newClientData = clientData;
}
+
+ /*
+ * This recursive call is OK, because we've changed the value
+ * of 'target'.
+ */
+
+ Tk_CreateSelHandler(tkwin, selection, target, proc, newClientData,
+ target);
}
}
}
diff --git a/tests/clipboard.test b/tests/clipboard.test
index 6077940..0f7e378 100644
--- a/tests/clipboard.test
+++ b/tests/clipboard.test
@@ -203,7 +203,7 @@ test clipboard-5.1 {Tk_ClipboardClear procedure} -setup {
list $result [lsort [clipboard get TARGETS]]
} -cleanup {
clipboard clear
-} -result {{MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}
+} -result {{MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}}
test clipboard-5.2 {Tk_ClipboardClear procedure} -setup {
clipboard clear
} -body {
@@ -216,7 +216,7 @@ test clipboard-5.2 {Tk_ClipboardClear procedure} -setup {
lappend result [lsort [clipboard get TARGETS]]
} -cleanup {
clipboard clear
-} -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW}}
+} -result {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW} {MULTIPLE TARGETS TEST TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}}
##############################################################################
diff --git a/tests/select.test b/tests/select.test
index 77bfb2e..9f2188d 100644
--- a/tests/select.test
+++ b/tests/select.test
@@ -238,7 +238,7 @@ test select-2.3 {Tk_DeleteSelHandler procedure} -constraints unix -setup {
selection handle -selection CLIPBOARD .f1 {}
list [lsort [selection get TARGETS]] \
[lsort [selection get -selection CLIPBOARD TARGETS]]
-} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW}}
+} -result {{MULTIPLE STRING TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING} {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW UTF8_STRING}}
test select-2.4 {Tk_DeleteSelHandler procedure} -constraints win -setup {
setup
} -body {