📄 tkselect.c
字号:
* } * * The interp and clientData arguments to proc will be the * same as the corresponding arguments to Tk_GetSelection. * The portion argument points to a character string * containing part of the selection, and numBytes indicates * the length of the portion, not including the terminating * NULL character. If the selection arrives in several pieces, * the "portion" arguments in separate calls will contain * successive parts of the selection. Proc should normally * return TCL_OK. If it detects an error then it should return * TCL_ERROR and leave an error message in interp->result; the * remainder of the selection retrieval will be aborted. * *-------------------------------------------------------------- */intTk_GetSelection(interp, tkwin, selection, target, proc, clientData) Tcl_Interp *interp; /* Interpreter to use for reporting * errors. */ Tk_Window tkwin; /* Window on whose behalf to retrieve * the selection (determines display * from which to retrieve). */ Atom selection; /* Selection to retrieve. */ Atom target; /* Desired form in which selection * is to be returned. */ Tk_GetSelProc *proc; /* Procedure to call to process the * selection, once it has been retrieved. */ ClientData clientData; /* Arbitrary value to pass to proc. */{ TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); } /* * If the selection is owned by a window managed by this * process, then call the retrieval procedure directly, * rather than going through the X server (it's dangerous * to go through the X server in this case because it could * result in deadlock if an INCR-style selection results). */ for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->selection == selection) break; } if (infoPtr != NULL) { register TkSelHandler *selPtr; int offset, result, count; char buffer[TK_SEL_BYTES_AT_ONCE+1]; TkSelInProgress ip; for (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList; selPtr != NULL; selPtr = selPtr->nextPtr) { if ((selPtr->target == target) && (selPtr->selection == selection)) { break; } } if (selPtr == NULL) { Atom type; count = TkSelDefaultSelection(infoPtr, target, buffer, TK_SEL_BYTES_AT_ONCE, &type); if (count > TK_SEL_BYTES_AT_ONCE) { panic("selection handler returned too many bytes"); } if (count < 0) { goto cantget; } buffer[count] = 0; result = (*proc)(clientData, interp, buffer); } else { offset = 0; result = TCL_OK; ip.selPtr = selPtr; ip.nextPtr = pendingPtr; pendingPtr = &ip; while (1) { count = (selPtr->proc)(selPtr->clientData, offset, buffer, TK_SEL_BYTES_AT_ONCE); if ((count < 0) || (ip.selPtr == NULL)) { pendingPtr = ip.nextPtr; goto cantget; } if (count > TK_SEL_BYTES_AT_ONCE) { panic("selection handler returned too many bytes"); } buffer[count] = '\0'; result = (*proc)(clientData, interp, buffer); if ((result != TCL_OK) || (count < TK_SEL_BYTES_AT_ONCE) || (ip.selPtr == NULL)) { break; } offset += count; } pendingPtr = ip.nextPtr; } return result; } /* * The selection is owned by some other process. */ return TkSelGetSelection(interp, tkwin, selection, target, proc, clientData); cantget: Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target), "\" not defined", (char *) NULL); return TCL_ERROR;}/* *-------------------------------------------------------------- * * Tk_SelectionCmd -- * * This procedure is invoked to process the "selection" Tcl * command. See the user documentation for details on what * it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */intTk_SelectionCmd(clientData, interp, argc, argv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ Tk_Window tkwin = (Tk_Window) clientData; char *path = NULL; Atom selection; char *selName = NULL; int c, count; size_t length; char **args; if (argc < 2) { sprintf(interp->result, "wrong # args: should be \"%.50s option ?arg arg ...?\"", argv[0]); return TCL_ERROR; } c = argv[1][0]; length = strlen(argv[1]); if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) { for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) { if (args[0][0] != '-') { break; } if (count < 2) { Tcl_AppendResult(interp, "value for \"", *args, "\" missing", (char *) NULL); return TCL_ERROR; } c = args[0][1]; length = strlen(args[0]); if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) { path = args[1]; } else if ((c == 's') && (strncmp(args[0], "-selection", length) == 0)) { selName = args[1]; } else { Tcl_AppendResult(interp, "unknown option \"", args[0], "\"", (char *) NULL); return TCL_ERROR; } } if (count == 1) { path = args[0]; } else if (count > 1) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " clear ?options?\"", (char *) NULL); return TCL_ERROR; } if (path != NULL) { tkwin = Tk_NameToWindow(interp, path, tkwin); } if (tkwin == NULL) { return TCL_ERROR; } if (selName != NULL) { selection = Tk_InternAtom(tkwin, selName); } else { selection = XA_PRIMARY; } Tk_ClearSelection(tkwin, selection); return TCL_OK; } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { Atom target; char *targetName = NULL; Tcl_DString selBytes; int result; for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) { if (args[0][0] != '-') { break; } if (count < 2) { Tcl_AppendResult(interp, "value for \"", *args, "\" missing", (char *) NULL); return TCL_ERROR; } c = args[0][1]; length = strlen(args[0]); if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) { path = args[1]; } else if ((c == 's') && (strncmp(args[0], "-selection", length) == 0)) { selName = args[1]; } else if ((c == 't') && (strncmp(args[0], "-type", length) == 0)) { targetName = args[1]; } else { Tcl_AppendResult(interp, "unknown option \"", args[0], "\"", (char *) NULL); return TCL_ERROR; } } if (path != NULL) { tkwin = Tk_NameToWindow(interp, path, tkwin); } if (tkwin == NULL) { return TCL_ERROR; } if (selName != NULL) { selection = Tk_InternAtom(tkwin, selName); } else { selection = XA_PRIMARY; } if (count > 1) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " get ?options?\"", (char *) NULL); return TCL_ERROR; } else if (count == 1) { target = Tk_InternAtom(tkwin, args[0]); } else if (targetName != NULL) { target = Tk_InternAtom(tkwin, targetName); } else { target = XA_STRING; } Tcl_DStringInit(&selBytes); result = Tk_GetSelection(interp, tkwin, selection, target, SelGetProc, (ClientData) &selBytes); if (result == TCL_OK) { Tcl_DStringResult(interp, &selBytes); } else { Tcl_DStringFree(&selBytes); } return result; } else if ((c == 'h') && (strncmp(argv[1], "handle", length) == 0)) { Atom target, format; char *targetName = NULL; char *formatName = NULL; register CommandInfo *cmdInfoPtr; int cmdLength; for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) { if (args[0][0] != '-') { break; } if (count < 2) { Tcl_AppendResult(interp, "value for \"", *args, "\" missing", (char *) NULL); return TCL_ERROR; } c = args[0][1]; length = strlen(args[0]); if ((c == 'f') && (strncmp(args[0], "-format", length) == 0)) { formatName = args[1]; } else if ((c == 's') && (strncmp(args[0], "-selection", length) == 0)) { selName = args[1]; } else if ((c == 't') && (strncmp(args[0], "-type", length) == 0)) { targetName = args[1]; } else { Tcl_AppendResult(interp, "unknown option \"", args[0], "\"", (char *) NULL); return TCL_ERROR; } } if ((count < 2) || (count > 4)) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " handle ?options? window command\"", (char *) NULL); return TCL_ERROR; } tkwin = Tk_NameToWindow(interp, args[0], tkwin); if (tkwin == NULL) { return TCL_ERROR; } if (selName != NULL) { selection = Tk_InternAtom(tkwin, selName); } else { selection = XA_PRIMARY; } if (count > 2) { target = Tk_InternAtom(tkwin, args[2]); } else if (targetName != NULL) { target = Tk_InternAtom(tkwin, targetName); } else { target = XA_STRING; } if (count > 3) { format = Tk_InternAtom(tkwin, args[3]); } else if (formatName != NULL) { format = Tk_InternAtom(tkwin, formatName); } else { format = XA_STRING; } cmdLength = strlen(args[1]); if (cmdLength == 0) { Tk_DeleteSelHandler(tkwin, selection, target); } else { cmdInfoPtr = (CommandInfo *) ckalloc((unsigned) ( sizeof(CommandInfo) - 3 + cmdLength)); cmdInfoPtr->interp = interp; cmdInfoPtr->cmdLength = cmdLength; strcpy(cmdInfoPtr->command, args[1]); Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand, (ClientData) cmdInfoPtr, format); } return TCL_OK; } else if ((c == 'o') && (strncmp(argv[1], "own", length) == 0)) { register LostCommand *lostPtr; char *script = NULL; int cmdLength; for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) { if (args[0][0] != '-') { break; } if (count < 2) { Tcl_AppendResult(interp, "value for \"", *args, "\" missing", (char *) NULL); return TCL_ERROR; } c = args[0][1]; length = strlen(args[0]); if ((c == 'c') && (strncmp(args[0], "-command", length) == 0)) { script = args[1]; } else if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) { path = args[1]; } else if ((c == 's') && (strncmp(args[0], "-selection", length) == 0)) { selName = args[1]; } else { Tcl_AppendResult(interp, "unknown option \"", args[0], "\"", (char *) NULL); return TCL_ERROR; } } if (count > 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " own ?options? ?window?\"", (char *) NULL); return TCL_ERROR; } if (selName != NULL) { selection = Tk_InternAtom(tkwin, selName); } else { selection = XA_PRIMARY; } if (count == 0) { TkSelectionInfo *infoPtr; TkWindow *winPtr; if (path != NULL) { tkwin = Tk_NameToWindow(interp, path, tkwin); } if (tkwin == NULL) { return TCL_ERROR; } winPtr = (TkWindow *)tkwin; for (infoPtr = winPtr->dispPtr->selectionInfoPtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->selection == selection) break; } /* * Ignore the internal clipboard window. */ if ((infoPtr != NULL) && (infoPtr->owner != winPtr->dispPtr->clipWindow)) { interp->result = Tk_PathName(infoPtr->owner); } return TCL_OK; } tkwin = Tk_NameToWindow(interp, args[0], tkwin); if (tkwin == NULL) { return TCL_ERROR; } if (count == 2) { script = args[1]; } if (script == NULL) { Tk_OwnSelection(tkwin, selection, (Tk_LostSelProc *) NULL, (ClientData) NULL); return TCL_OK; } cmdLength = strlen(script); lostPtr = (LostCommand *) ckalloc((unsigned) (sizeof(LostCommand) -3 + cmdLength)); lostPtr->interp = interp; strcpy(lostPtr->command, script); Tk_OwnSelection(tkwin, selection, LostSelection, (ClientData) lostPtr); return TCL_OK; } else { sprintf(interp->result, "bad option \"%.50s\": must be clear, get, handle, or own", argv[1]); return TCL_ERROR; }}/* *---------------------------------------------------------------------- * * TkSelDeadWindow -- * * This procedure is invoked just before a TkWindow is deleted. * It performs selection-related cleanup. * * Results:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -