summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--generic/tkSelect.c27
-rw-r--r--tests/select.test17
-rw-r--r--unix/tkUnixSelect.c166
4 files changed, 103 insertions, 111 deletions
diff --git a/ChangeLog b/ChangeLog
index 9f127e8..b8032fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2005-11-22 Donal K. Fellows <donal.k.fellows@man.ac.uk>
+ * unix/tkUnixSelect.c (SelCvtToX, SelCvtFromX): Backport of fixes for
+ * generic/tkSelect.c (TkSelDefaultSelection): "spaces in atom names"
+ * tests/select.test (select-9.5): problems. [Bug 1353414]
+
* library/tkfbox.tcl (::tk::dialog::file::): Correct the quoting of
the script used in variable traces so that widget names with spaces in
will work. [Bug 1335485]
diff --git a/generic/tkSelect.c b/generic/tkSelect.c
index d62aa43..73e41d8 100644
--- a/generic/tkSelect.c
+++ b/generic/tkSelect.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: tkSelect.c,v 1.13 2003/01/14 19:24:56 jenglish Exp $
+ * RCS: @(#) $Id: tkSelect.c,v 1.13.2.1 2005/11/22 11:32:37 dkf Exp $
*/
#include "tkInt.h"
@@ -1489,29 +1489,32 @@ TkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr)
if (target == dispPtr->targetsAtom) {
register TkSelHandler *selPtr;
- CONST char *atomString;
- int length, atomLength;
+ int length;
+ Tcl_DString ds;
if (maxBytes < 50) {
return -1;
}
- strcpy(buffer, "MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW");
- length = strlen(buffer);
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds,
+ "MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW", -1);
for (selPtr = winPtr->selHandlerList; selPtr != NULL;
selPtr = selPtr->nextPtr) {
if ((selPtr->selection == infoPtr->selection)
&& (selPtr->target != dispPtr->applicationAtom)
&& (selPtr->target != dispPtr->windowAtom)) {
- atomString = Tk_GetAtomName((Tk_Window) winPtr,
+ CONST char *atomString = Tk_GetAtomName((Tk_Window) winPtr,
selPtr->target);
- atomLength = strlen(atomString) + 1;
- if ((length + atomLength) >= maxBytes) {
- return -1;
- }
- sprintf(buffer+length, " %s", atomString);
- length += atomLength;
+ Tcl_DStringAppendElement(&ds, atomString);
}
}
+ length = Tcl_DStringLength(&ds);
+ if (length >= maxBytes) {
+ Tcl_DStringFree(&ds);
+ return -1;
+ }
+ memcpy(buffer, Tcl_DStringValue(&ds), (unsigned) (1+length));
+ Tcl_DStringFree(&ds);
*typePtr = XA_ATOM;
return length;
}
diff --git a/tests/select.test b/tests/select.test
index 0e24c7c..4e63f9b 100644
--- a/tests/select.test
+++ b/tests/select.test
@@ -6,7 +6,7 @@
# Copyright (c) 1998-1999 by Scriptics Corporation.
# All rights reserved.
#
-# RCS: @(#) $Id: select.test,v 1.9 2002/07/13 20:28:35 dgp Exp $
+# RCS: @(#) $Id: select.test,v 1.9.2.1 2005/11/22 11:32:37 dkf Exp $
#
# Note: Multiple display selection handling will only be tested if the
@@ -848,6 +848,21 @@ test select-9.4 {SelCvtToX and SelCvtFromX procedures} {unixOnly} {
cleanupbg
lappend result $selInfo
} {{0x10 0x0 0x20} {TEST 0 4000}}
+test select-9.5 {SelCvtToX and SelCvtFromX procedures} -setup {
+ setup
+ setupbg
+} -constraints unix -body {
+ # Ensure that lists of atoms are constructed correctly, even when the
+ # atom names have spaces in. [Bug 1353414]
+ set selValue "foo bar"
+ set selInfo ""
+ set selType {text/x-tk-test;detail="foo bar"}
+ selection handle -selection PRIMARY -format STRING -type $selType \
+ .f1 [list handler $selType]
+ lsort [dobg {selection get TARGETS}]
+} -cleanup {
+ cleanupbg
+} -result {MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW {text/x-tk-test;detail="foo bar"}}
##############################################################################
diff --git a/unix/tkUnixSelect.c b/unix/tkUnixSelect.c
index 92add7f..2592d33 100644
--- a/unix/tkUnixSelect.c
+++ b/unix/tkUnixSelect.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkUnixSelect.c,v 1.11 2002/10/01 08:48:08 dkf Exp $
+ * RCS: @(#) $Id: tkUnixSelect.c,v 1.11.2.1 2005/11/22 11:32:37 dkf Exp $
*/
#include "tkInt.h"
@@ -99,8 +99,8 @@ static TkSelRetrievalInfo *pendingRetrievals = NULL;
static void ConvertSelection _ANSI_ARGS_((TkWindow *winPtr,
XSelectionRequestEvent *eventPtr));
static void IncrTimeoutProc _ANSI_ARGS_((ClientData clientData));
-static char * SelCvtFromX _ANSI_ARGS_((long *propPtr, int numValues,
- Atom type, Tk_Window tkwin));
+static void SelCvtFromX _ANSI_ARGS_((long *propPtr, int numValues,
+ Atom type, Tk_Window tkwin, Tcl_DString *dsPtr));
static long * SelCvtToX _ANSI_ARGS_((char *string, Atom type,
Tk_Window tkwin, int *numLongsPtr));
static int SelectionSize _ANSI_ARGS_((TkSelHandler *selPtr));
@@ -461,11 +461,16 @@ TkSelPropProc(eventPtr)
formatType, (Tk_Window) incrPtr->winPtr,
&numItems);
+ if (propPtr == NULL) {
+ numItems = 0;
+ }
XChangeProperty(eventPtr->xproperty.display,
eventPtr->xproperty.window, eventPtr->xproperty.atom,
formatType, 32, PropModeReplace,
(unsigned char *) propPtr, numItems);
- ckfree(propPtr);
+ if (propPtr != NULL) {
+ ckfree(propPtr);
+ }
}
Tk_DeleteErrorHandler(errorHandler);
@@ -676,7 +681,7 @@ TkSelEventProc(tkwin, eventPtr)
Tk_DeleteEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc,
(ClientData) retrPtr);
} else {
- char *string;
+ Tcl_DString ds;
if (format != 32) {
char buf[64 + TCL_INTEGER_SPACE];
@@ -688,14 +693,15 @@ TkSelEventProc(tkwin, eventPtr)
retrPtr->result = TCL_ERROR;
return;
}
- string = SelCvtFromX((long *) propInfo, (int) numItems, type,
- (Tk_Window) winPtr);
+ Tcl_DStringInit(&ds);
+ SelCvtFromX((long *) propInfo, (int) numItems, type,
+ (Tk_Window) winPtr, &ds);
interp = retrPtr->interp;
Tcl_Preserve((ClientData) interp);
retrPtr->result = (*retrPtr->proc)(retrPtr->clientData,
- interp, string);
+ interp, Tcl_DStringValue(&ds));
Tcl_Release((ClientData) interp);
- ckfree(string);
+ Tcl_DStringFree(&ds);
}
XFree(propInfo);
return;
@@ -1000,6 +1006,9 @@ ConvertSelection(winPtr, eventPtr)
} else {
propPtr = (char *) SelCvtToX((char *) buffer,
type, (Tk_Window) winPtr, &numItems);
+ if (propPtr == NULL) {
+ goto refuse;
+ }
format = 32;
XChangeProperty(reply.display, reply.requestor,
property, type, format, PropModeReplace,
@@ -1260,7 +1269,7 @@ SelRcvIncrProc(clientData, eventPtr)
} else if (numItems == 0) {
retrPtr->result = TCL_OK;
} else {
- char *string;
+ Tcl_DString ds;
if (format != 32) {
char buf[64 + TCL_INTEGER_SPACE];
@@ -1272,19 +1281,21 @@ SelRcvIncrProc(clientData, eventPtr)
retrPtr->result = TCL_ERROR;
goto done;
}
- string = SelCvtFromX((long *) propInfo, (int) numItems, type,
- (Tk_Window) retrPtr->winPtr);
+ Tcl_DStringInit(&ds);
+ SelCvtFromX((long *) propInfo, (int) numItems, type,
+ (Tk_Window) retrPtr->winPtr, &ds);
interp = retrPtr->interp;
Tcl_Preserve((ClientData) interp);
- result = (*retrPtr->proc)(retrPtr->clientData, interp, string);
+ result = (*retrPtr->proc)(retrPtr->clientData, interp,
+ Tcl_DStringValue(&ds));
Tcl_Release((ClientData) interp);
+ Tcl_DStringFree(&ds);
if (result != TCL_OK) {
retrPtr->result = result;
}
- ckfree(string);
}
- done:
+ done:
XFree(propInfo);
retrPtr->idleTime = 0;
}
@@ -1405,28 +1416,21 @@ SelCvtToX(string, type, tkwin, numLongsPtr)
int *numLongsPtr; /* Number of 32-bit words contained in the
* result. */
{
- register char *p;
- char *field;
- int numFields;
- long *propPtr, *longPtr;
-#define MAX_ATOM_NAME_LENGTH 100
- char atomName[MAX_ATOM_NAME_LENGTH+1];
+ const char **field;
+ int numFields, i;
+ long *propPtr;
/*
- * The string is assumed to consist of fields separated by spaces.
- * The property gets generated by converting each field to an
- * integer number, in one of two ways:
- * 1. If type is XA_ATOM, convert each field to its corresponding
- * atom.
- * 2. If type is anything else, convert each field from an ASCII number
- * to a 32-bit binary number.
+ * The string is assumed to consist of fields separated by spaces. The
+ * property gets generated by converting each field to an integer number,
+ * in one of two ways:
+ * 1. If type is XA_ATOM, convert each field to its corresponding atom.
+ * 2. If type is anything else, convert each field from an ASCII number to
+ * a 32-bit binary number.
*/
- numFields = 1;
- for (p = string; *p != 0; p++) {
- if (isspace(UCHAR(*p))) {
- numFields++;
- }
+ if (Tcl_SplitList(NULL, string, &numFields, &field) != TCL_OK) {
+ return NULL;
}
propPtr = (long *) ckalloc((unsigned) numFields*sizeof(long));
@@ -1434,34 +1438,27 @@ SelCvtToX(string, type, tkwin, numLongsPtr)
* Convert the fields one-by-one.
*/
- for (longPtr = propPtr, *numLongsPtr = 0, p = string;
- ; longPtr++, (*numLongsPtr)++) {
- while (isspace(UCHAR(*p))) {
- p++;
- }
- if (*p == 0) {
- break;
- }
- field = p;
- while ((*p != 0) && !isspace(UCHAR(*p))) {
- p++;
- }
+ for (i=0 ; i<numFields ; i++) {
if (type == XA_ATOM) {
- int length;
-
- length = p - field;
- if (length > MAX_ATOM_NAME_LENGTH) {
- length = MAX_ATOM_NAME_LENGTH;
- }
- strncpy(atomName, field, (unsigned) length);
- atomName[length] = 0;
- *longPtr = (long) Tk_InternAtom(tkwin, atomName);
+ propPtr[i] = (long) Tk_InternAtom(tkwin, field[i]);
} else {
char *dummy;
- *longPtr = strtol(field, &dummy, 0);
+ /*
+ * If this fails to parse a number, we just plunge on regardless
+ * anyway.
+ */
+
+ propPtr[i] = strtol(field[i], &dummy, 0);
}
}
+
+ /*
+ * Release the parsed list.
+ */
+
+ ckfree((char *) field);
+ *numLongsPtr = i;
return propPtr;
}
@@ -1476,9 +1473,8 @@ SelCvtToX(string, type, tkwin, numLongsPtr)
* procedure is the inverse of SelCvtToX.
*
* Results:
- * The return value is the string equivalent of "property". It is
- * malloc-ed and should be freed by the caller when no longer
- * needed.
+ * The return value (stored in a Tcl_DString) is the string equivalent of
+ * "property". It is up to the caller to initialize and free the DString.
*
* Side effects:
* None.
@@ -1486,60 +1482,34 @@ SelCvtToX(string, type, tkwin, numLongsPtr)
*----------------------------------------------------------------------
*/
-static char *
-SelCvtFromX(propPtr, numValues, type, tkwin)
+static void
+SelCvtFromX(propPtr, numValues, type, tkwin, dsPtr)
register long *propPtr; /* Property value from X. */
int numValues; /* Number of 32-bit values in property. */
Atom type; /* Type of property Should not be
* XA_STRING (if so, don't bother calling
* this procedure at all). */
Tk_Window tkwin; /* Window to use for atom conversion. */
+ Tcl_DString *dsPtr; /* Where to store the converted string. */
{
- char *result;
- int resultSpace, curSize, fieldSize;
- CONST char *atomName;
-
/*
- * Convert each long in the property to a string value, which is
- * either the name of an atom (if type is XA_ATOM) or a hexadecimal
- * string. Make an initial guess about the size of the result, but
- * be prepared to enlarge the result if necessary.
+ * Convert each long in the property to a string value, which is either
+ * the name of an atom (if type is XA_ATOM) or a hexadecimal string. We
+ * build the list in a Tcl_DString because this is easier than trying to
+ * get the quoting correct ourselves; this is tricky because atoms can
+ * contain spaces in their names (encountered when the atoms are really
+ * MIME types). [Bug 1353414]
*/
- resultSpace = 12*numValues+1;
- curSize = 0;
- atomName = ""; /* Not needed, but eliminates compiler warning. */
- result = (char *) ckalloc((unsigned) resultSpace);
- *result = '\0';
for ( ; numValues > 0; propPtr++, numValues--) {
if (type == XA_ATOM) {
- atomName = Tk_GetAtomName(tkwin, (Atom) *propPtr);
- fieldSize = strlen(atomName) + 1;
+ Tcl_DStringAppendElement(dsPtr,
+ Tk_GetAtomName(tkwin, (Atom) *propPtr));
} else {
- fieldSize = 12;
- }
- if (curSize+fieldSize >= resultSpace) {
- char *newResult;
+ char buf[12];
- resultSpace *= 2;
- if (curSize+fieldSize >= resultSpace) {
- resultSpace = curSize + fieldSize + 1;
- }
- newResult = (char *) ckalloc((unsigned) resultSpace);
- strncpy(newResult, result, (unsigned) curSize);
- ckfree(result);
- result = newResult;
- }
- if (curSize != 0) {
- result[curSize] = ' ';
- curSize++;
- }
- if (type == XA_ATOM) {
- strcpy(result+curSize, atomName);
- } else {
- sprintf(result+curSize, "0x%x", (unsigned int) *propPtr);
+ sprintf(buf, "0x%x", (unsigned int) *propPtr);
+ Tcl_DStringAppendElement(dsPtr, buf);
}
- curSize += strlen(result+curSize);
}
- return result;
}