diff options
-rw-r--r-- | doc/CrtSelHdlr.3 | 13 | ||||
-rw-r--r-- | generic/tkSelect.c | 78 | ||||
-rw-r--r-- | tests/clipboard.test | 4 | ||||
-rw-r--r-- | tests/select.test | 2 |
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 { |