From 4fe67b59a8c7eb7b682da1552f3c6d73c091902f Mon Sep 17 00:00:00 2001 From: dkf Date: Sun, 13 Nov 2005 22:32:58 +0000 Subject: Fix [Bug 1353414] by doing the list generation using standard Tcl utilities. Also simplifies the code quite a bit (at the expense of an OUT parameter instead of a return value). --- ChangeLog | 3 ++ unix/tkUnixSelect.c | 85 +++++++++++++++++++---------------------------------- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5b45a96..fecaf52 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2005-11-13 Donal K. Fellows + * unix/tkUnixSelect.c (SelCvtFromX): Generate string forms of the + advanced selection types in a Tcl_DString. This makes fixing [Bug + 1353414] trivial, and simplifies the code at the same time. * tests/select.test (select-9.5): Added test for [Bug 1353414] 2005-11-10 Donal K. Fellows diff --git a/unix/tkUnixSelect.c b/unix/tkUnixSelect.c index 4c94056..f5decdb 100644 --- a/unix/tkUnixSelect.c +++ b/unix/tkUnixSelect.c @@ -8,7 +8,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.14 2005/10/21 01:51:45 dkf Exp $ + * RCS: @(#) $Id: tkUnixSelect.c,v 1.15 2005/11/13 22:32:58 dkf Exp $ */ #include "tkInt.h" @@ -93,8 +93,8 @@ static TkSelRetrievalInfo *pendingRetrievals = NULL; static void ConvertSelection(TkWindow *winPtr, XSelectionRequestEvent *eventPtr); static void IncrTimeoutProc(ClientData clientData); -static char * SelCvtFromX(long *propPtr, int numValues, Atom type, - Tk_Window tkwin); +static void SelCvtFromX(long *propPtr, int numValues, Atom type, + Tk_Window tkwin, Tcl_DString *dsPtr); static long * SelCvtToX(char *string, Atom type, Tk_Window tkwin, int *numLongsPtr); static int SelectionSize(TkSelHandler *selPtr); @@ -666,7 +666,7 @@ TkSelEventProc( Tk_DeleteEventHandler(tkwin, PropertyChangeMask, SelRcvIncrProc, (ClientData) retrPtr); } else { - char *string; + Tcl_DString ds; if (format != 32) { char buf[64 + TCL_INTEGER_SPACE]; @@ -678,14 +678,15 @@ TkSelEventProc( 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; @@ -1241,7 +1242,7 @@ SelRcvIncrProc( } else if (numItems == 0) { retrPtr->result = TCL_OK; } else { - char *string; + Tcl_DString ds; if (format != 32) { char buf[64 + TCL_INTEGER_SPACE]; @@ -1253,16 +1254,18 @@ SelRcvIncrProc( 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: @@ -1457,8 +1460,8 @@ SelCvtToX( * 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. @@ -1466,62 +1469,36 @@ SelCvtToX( *---------------------------------------------------------------------- */ -static char * +static void SelCvtFromX( 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 function * at all). */ - Tk_Window tkwin) /* Window to use for atom conversion. */ + 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. + * 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; } /* -- cgit v0.12