📄 tkselect.c
字号:
* None. * * Side effects: * Frees up memory associated with the selection. * *---------------------------------------------------------------------- */voidTkSelDeadWindow(winPtr) register TkWindow *winPtr; /* Window that's being deleted. */{ register TkSelHandler *selPtr; register TkSelInProgress *ipPtr; TkSelectionInfo *infoPtr, *prevPtr, *nextPtr; /* * While deleting all the handlers, be careful to check whether * ConvertSelection or TkSelPropProc are about to process one of the * deleted handlers. */ while (winPtr->selHandlerList != NULL) { selPtr = winPtr->selHandlerList; winPtr->selHandlerList = selPtr->nextPtr; for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { if (ipPtr->selPtr == selPtr) { ipPtr->selPtr = NULL; } } if (selPtr->proc == HandleTclCommand) { ckfree((char *) selPtr->clientData); } ckfree((char *) selPtr); } /* * Remove selections owned by window being deleted. */ for (infoPtr = winPtr->dispPtr->selectionInfoPtr, prevPtr = NULL; infoPtr != NULL; infoPtr = nextPtr) { nextPtr = infoPtr->nextPtr; if (infoPtr->owner == (Tk_Window) winPtr) { if (infoPtr->clearProc == LostSelection) { ckfree((char *) infoPtr->clearData); } ckfree((char *) infoPtr); infoPtr = prevPtr; if (prevPtr == NULL) { winPtr->dispPtr->selectionInfoPtr = nextPtr; } else { prevPtr->nextPtr = nextPtr; } } prevPtr = infoPtr; }}/* *---------------------------------------------------------------------- * * TkSelInit -- * * Initialize selection-related information for a display. * * Results: * None. * * Side effects: * Selection-related information is initialized. * *---------------------------------------------------------------------- */voidTkSelInit(tkwin) Tk_Window tkwin; /* Window token (used to find * display to initialize). */{ register TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; /* * Fetch commonly-used atoms. */ dispPtr->multipleAtom = Tk_InternAtom(tkwin, "MULTIPLE"); dispPtr->incrAtom = Tk_InternAtom(tkwin, "INCR"); dispPtr->targetsAtom = Tk_InternAtom(tkwin, "TARGETS"); dispPtr->timestampAtom = Tk_InternAtom(tkwin, "TIMESTAMP"); dispPtr->textAtom = Tk_InternAtom(tkwin, "TEXT"); dispPtr->compoundTextAtom = Tk_InternAtom(tkwin, "COMPOUND_TEXT"); dispPtr->applicationAtom = Tk_InternAtom(tkwin, "TK_APPLICATION"); dispPtr->windowAtom = Tk_InternAtom(tkwin, "TK_WINDOW"); dispPtr->clipboardAtom = Tk_InternAtom(tkwin, "CLIPBOARD");}/* *---------------------------------------------------------------------- * * TkSelClearSelection -- * * This procedure is invoked to process a SelectionClear event. * * Results: * None. * * Side effects: * Invokes the clear procedure for the window which lost the * selection. * *---------------------------------------------------------------------- */voidTkSelClearSelection(tkwin, eventPtr) Tk_Window tkwin; /* Window for which event was targeted. */ register XEvent *eventPtr; /* X SelectionClear event. */{ register TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; TkSelectionInfo *prevPtr; /* * Invoke clear procedure for window that just lost the selection. This * code is a bit tricky, because any callbacks due to selection changes * between windows managed by the process have already been made. Thus, * ignore the event unless it refers to the window that's currently the * selection owner and the event was generated after the server saw the * SetSelectionOwner request. */ for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->selection == eventPtr->xselectionclear.selection) { break; } prevPtr = infoPtr; } if (infoPtr != NULL && (infoPtr->owner == tkwin) && (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) { if (prevPtr == NULL) { dispPtr->selectionInfoPtr = infoPtr->nextPtr; } else { prevPtr->nextPtr = infoPtr->nextPtr; } /* * Because of reentrancy problems, calling clearProc must be done * after the infoPtr has been removed from the selectionInfoPtr * list (clearProc could modify the list, e.g. by creating * a new selection). */ if (infoPtr->clearProc != NULL) { (*infoPtr->clearProc)(infoPtr->clearData); } ckfree((char *) infoPtr); }}/* *-------------------------------------------------------------- * * SelGetProc -- * * This procedure is invoked to process pieces of the selection * as they arrive during "selection get" commands. * * Results: * Always returns TCL_OK. * * Side effects: * Bytes get appended to the dynamic string pointed to by the * clientData argument. * *-------------------------------------------------------------- */ /* ARGSUSED */static intSelGetProc(clientData, interp, portion) ClientData clientData; /* Dynamic string holding partially * assembled selection. */ Tcl_Interp *interp; /* Interpreter used for error * reporting (not used). */ char *portion; /* New information to be appended. */{ Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1); return TCL_OK;}/* *---------------------------------------------------------------------- * * HandleTclCommand -- * * This procedure acts as selection handler for handlers created * by the "selection handle" command. It invokes a Tcl command to * retrieve the selection. * * Results: * The return value is a count of the number of bytes actually * stored at buffer, or -1 if an error occurs while executing * the Tcl command to retrieve the selection. * * Side effects: * None except for things done by the Tcl command. * *---------------------------------------------------------------------- */static intHandleTclCommand(clientData, offset, buffer, maxBytes) ClientData clientData; /* Information about command to execute. */ int offset; /* Return selection bytes starting at this * offset. */ char *buffer; /* Place to store converted selection. */ int maxBytes; /* Maximum # of bytes to store at buffer. */{ CommandInfo *cmdInfoPtr = (CommandInfo *) clientData; int spaceNeeded, length;#define MAX_STATIC_SIZE 100 char staticSpace[MAX_STATIC_SIZE]; char *command; Tcl_Interp *interp; Tcl_DString oldResult; /* * We must copy the interpreter pointer from CommandInfo because the * command could delete the handler, freeing the CommandInfo data before we * are done using it. We must also protect the interpreter from being * deleted too soo. */ interp = cmdInfoPtr->interp; Tcl_Preserve((ClientData) interp); /* * First, generate a command by taking the command string * and appending the offset and maximum # of bytes. */ spaceNeeded = cmdInfoPtr->cmdLength + 30; if (spaceNeeded < MAX_STATIC_SIZE) { command = staticSpace; } else { command = (char *) ckalloc((unsigned) spaceNeeded); } sprintf(command, "%s %d %d", cmdInfoPtr->command, offset, maxBytes); /* * Execute the command. Be sure to restore the state of the * interpreter after executing the command. */ Tcl_DStringInit(&oldResult); Tcl_DStringGetResult(interp, &oldResult); if (TkCopyAndGlobalEval(interp, command) == TCL_OK) { length = strlen(interp->result); if (length > maxBytes) { length = maxBytes; } memcpy((VOID *) buffer, (VOID *) interp->result, (size_t) length); buffer[length] = '\0'; } else { length = -1; } Tcl_DStringResult(interp, &oldResult); if (command != staticSpace) { ckfree(command); } Tcl_Release((ClientData) interp); return length;}/* *---------------------------------------------------------------------- * * TkSelDefaultSelection -- * * This procedure is called to generate selection information * for a few standard targets such as TIMESTAMP and TARGETS. * It is invoked only if no handler has been declared by the * application. * * Results: * If "target" is a standard target understood by this procedure, * the selection is converted to that form and stored as a * character string in buffer. The type of the selection (e.g. * STRING or ATOM) is stored in *typePtr, and the return value is * a count of the # of non-NULL bytes at buffer. If the target * wasn't understood, or if there isn't enough space at buffer * to hold the entire selection (no INCR-mode transfers for this * stuff!), then -1 is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */intTkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr) TkSelectionInfo *infoPtr; /* Info about selection being retrieved. */ Atom target; /* Desired form of selection. */ char *buffer; /* Place to put selection characters. */ int maxBytes; /* Maximum # of bytes to store at buffer. */ Atom *typePtr; /* Store here the type of the selection, * for use in converting to proper X format. */{ register TkWindow *winPtr = (TkWindow *) infoPtr->owner; TkDisplay *dispPtr = winPtr->dispPtr; if (target == dispPtr->timestampAtom) { if (maxBytes < 20) { return -1; } sprintf(buffer, "0x%x", (unsigned int) infoPtr->time); *typePtr = XA_INTEGER; return strlen(buffer); } if (target == dispPtr->targetsAtom) { register TkSelHandler *selPtr; char *atomString; int length, atomLength; if (maxBytes < 50) { return -1; } strcpy(buffer, "MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW"); length = strlen(buffer); 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, selPtr->target); atomLength = strlen(atomString) + 1; if ((length + atomLength) >= maxBytes) { return -1; } sprintf(buffer+length, " %s", atomString); length += atomLength; } } *typePtr = XA_ATOM; return length; } if (target == dispPtr->applicationAtom) { int length; char *name = winPtr->mainPtr->winPtr->nameUid; length = strlen(name); if (maxBytes <= length) { return -1; } strcpy(buffer, name); *typePtr = XA_STRING; return length; } if (target == dispPtr->windowAtom) { int length; char *name = winPtr->pathName; length = strlen(name); if (maxBytes <= length) { return -1; } strcpy(buffer, name); *typePtr = XA_STRING; return length; } return -1;}/* *---------------------------------------------------------------------- * * LostSelection -- * * This procedure is invoked when a window has lost ownership of * the selection and the ownership was claimed with the command * "selection own". * * Results: * None. * * Side effects: * A Tcl script is executed; it can do almost anything. * *---------------------------------------------------------------------- */static voidLostSelection(clientData) ClientData clientData; /* Pointer to CommandInfo structure. */{ LostCommand *lostPtr = (LostCommand *) clientData; char *oldResultString; Tcl_FreeProc *oldFreeProc; Tcl_Interp *interp; interp = lostPtr->interp; Tcl_Preserve((ClientData) interp); /* * Execute the command. Save the interpreter's result, if any, and * restore it after executing the command. */ oldFreeProc = interp->freeProc; if (oldFreeProc != TCL_STATIC) { oldResultString = interp->result; } else { oldResultString = (char *) ckalloc((unsigned) (strlen(interp->result) + 1)); strcpy(oldResultString, interp->result); oldFreeProc = TCL_DYNAMIC; } interp->freeProc = TCL_STATIC; if (TkCopyAndGlobalEval(interp, lostPtr->command) != TCL_OK) { Tcl_BackgroundError(interp); } Tcl_FreeResult(interp); interp->result = oldResultString; interp->freeProc = oldFreeProc; Tcl_Release((ClientData) interp); /* * Free the storage for the command, since we're done with it now. */ ckfree((char *) lostPtr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -