diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2005-11-22 11:32:35 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2005-11-22 11:32:35 (GMT) |
commit | d8d6f63a208246d2f1b9366a3c009b0438e84e28 (patch) | |
tree | a90c2e014e2a1d92cda19a88347eaa9f722e56f2 /unix/tkUnixSelect.c | |
parent | f0d62bb7554a60f4229c29e7f8bcd6150fb3a044 (diff) | |
download | tk-d8d6f63a208246d2f1b9366a3c009b0438e84e28.zip tk-d8d6f63a208246d2f1b9366a3c009b0438e84e28.tar.gz tk-d8d6f63a208246d2f1b9366a3c009b0438e84e28.tar.bz2 |
Backport of fixes for [Bug 1353414]
Diffstat (limited to 'unix/tkUnixSelect.c')
-rw-r--r-- | unix/tkUnixSelect.c | 166 |
1 files changed, 68 insertions, 98 deletions
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; } |