📄 textsel.c
字号:
*type = XA_STRING; *value = (XtPointer)BufGetSelectionText(buf); *length = strlen((char *)*value); *format = 8; BufUnsubstituteNullChars(*value, buf); return True; } /* target is "TARGETS", return a list of targets we can handle */ if (*target == getAtom(display, A_TARGETS)) { targets = (Atom *)XtMalloc(sizeof(Atom) * N_SELECT_TARGETS); targets[0] = XA_STRING; targets[1] = getAtom(display, A_TEXT); targets[2] = getAtom(display, A_TARGETS); targets[3] = getAtom(display, A_MULTIPLE); targets[4] = getAtom(display, A_TIMESTAMP); targets[5] = getAtom(display, A_INSERT_SELECTION); targets[6] = getAtom(display, A_DELETE); *type = XA_ATOM; *value = (XtPointer)targets; *length = N_SELECT_TARGETS; *format = 32; return True; } /* target is "INSERT_SELECTION": 1) get the information about what selection and target to use to get the text to insert, from the property named in the property field of the selection request event. 2) initiate a get value request for the selection and target named in the property, and WAIT until it completes */ if (*target == getAtom(display, A_INSERT_SELECTION)) { if (((TextWidget)w)->text.readOnly) return False; if (XGetWindowProperty(event->display, event->requestor, event->property, 0, 2, False, AnyPropertyType, &dummyAtom, &getFmt, &nItems, &dummyULong, (unsigned char **)&reqAtoms) != Success || getFmt != 32 || nItems != 2) return False; if (reqAtoms[1] != XA_STRING) return False; XtGetSelectionValue(w, reqAtoms[0], reqAtoms[1], getInsertSelectionCB, &result, event->time); XFree((char *)reqAtoms); while (result == INSERT_WAITING) { XtAppNextEvent(XtWidgetToApplicationContext(w), &nextEvent); XtDispatchEvent(&nextEvent); } *type = getAtom(display, A_INSERT_SELECTION); *format = 8; *value = NULL; *length = 0; return result == SUCCESSFUL_INSERT; } /* target is "DELETE": delete primary selection */ if (*target == getAtom(display, A_DELETE)) { BufRemoveSelected(buf); *length = 0; *format = 8; *type = getAtom(display, A_DELETE); *value = NULL; return True; } /* targets TIMESTAMP and MULTIPLE are handled by the toolkit, any others are unrecognized, return False */ return False;}static void loseSelectionCB(Widget w, Atom *selType){ TextWidget tw = (TextWidget)w; selection *sel = &tw->text.textD->buffer->primary; char zeroWidth = sel->rectangular ? sel->zeroWidth : 0; /* For zero width rect. sel. we give up the selection but keep the zero width tag. */ tw->text.selectionOwner = False; BufUnselect(tw->text.textD->buffer); sel->zeroWidth = zeroWidth;}/*** Selection converter procedure used by the widget to (temporarily) provide** the secondary selection data to a single requestor who has been asked** to insert it.*/static Boolean convertSecondaryCB(Widget w, Atom *selType, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format){ textBuffer *buf = ((TextWidget)w)->text.textD->buffer; /* target must be string */ if (*target != XA_STRING && *target != getAtom(XtDisplay(w), A_TEXT)) return False; /* Return the contents of the secondary selection. The memory allocated here is freed by the X toolkit */ *type = XA_STRING; *value = (XtPointer)BufGetSecSelectText(buf); *length = strlen((char *)*value); *format = 8; BufUnsubstituteNullChars(*value, buf); return True;}static void loseSecondaryCB(Widget w, Atom *selType){ /* do nothing, secondary selections are transient anyhow, and it will go away on its own */}/*** Selection converter procedure used by the widget when it owns the Motif** destination, to handle INSERT_SELECTION requests.*/static Boolean convertMotifDestCB(Widget w, Atom *selType, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format){ XSelectionRequestEvent *event = XtGetSelectionRequest(w, *selType, 0); Display *display = XtDisplay(w); Atom *targets, dummyAtom; unsigned long nItems, dummyULong; Atom *reqAtoms; int getFmt, result = INSERT_WAITING; XEvent nextEvent; /* target is "TARGETS", return a list of targets it can handle */ if (*target == getAtom(display, A_TARGETS)) { targets = (Atom *)XtMalloc(sizeof(Atom) * 3); targets[0] = getAtom(display, A_TARGETS); targets[1] = getAtom(display, A_TIMESTAMP); targets[2] = getAtom(display, A_INSERT_SELECTION); *type = XA_ATOM; *value = (XtPointer)targets; *length = 3; *format = 32; return True; } /* target is "INSERT_SELECTION": 1) get the information about what selection and target to use to get the text to insert, from the property named in the property field of the selection request event. 2) initiate a get value request for the selection and target named in the property, and WAIT until it completes */ if (*target == getAtom(display, A_INSERT_SELECTION)) { if (((TextWidget)w)->text.readOnly) return False; if (XGetWindowProperty(event->display, event->requestor, event->property, 0, 2, False, AnyPropertyType, &dummyAtom, &getFmt, &nItems, &dummyULong, (unsigned char **)&reqAtoms) != Success || getFmt != 32 || nItems != 2) return False; if (reqAtoms[1] != XA_STRING) return False; XtGetSelectionValue(w, reqAtoms[0], reqAtoms[1], getInsertSelectionCB, &result, event->time); XFree((char *)reqAtoms); while (result == INSERT_WAITING) { XtAppNextEvent(XtWidgetToApplicationContext(w), &nextEvent); XtDispatchEvent(&nextEvent); } *type = getAtom(display, A_INSERT_SELECTION); *format = 8; *value = NULL; *length = 0; return result == SUCCESSFUL_INSERT; } /* target TIMESTAMP is handled by the toolkit and not passed here, any others are unrecognized */ return False;}static void loseMotifDestCB(Widget w, Atom *selType){ ((TextWidget)w)->text.motifDestOwner = False; if (((TextWidget)w)->text.textD->cursorStyle == CARET_CURSOR) TextDSetCursorStyle(((TextWidget)w)->text.textD, DIM_CURSOR);}/*** Event handler for SelectionNotify events, to finish off INSERT_SELECTION** requests which must be done through the lower** level (and more complicated) XLib selection mechanism. Matches the** time stamp in the request against the time stamp stored when the selection** request was made to find the selectionNotify event that it was installed** to catch. When it finds the correct event, it does the action it was** installed to do, and removes itself and its backup timer (which would do** the clean up if the selectionNotify event never arrived.)*/static void selectNotifyEH(Widget w, XtPointer data, XEvent *event, Boolean *continueDispatch){ textBuffer *buf = ((TextWidget)w)->text.textD->buffer; XSelectionEvent *e = (XSelectionEvent *)event; selectNotifyInfo *cbInfo = (selectNotifyInfo *)data; int selStart, selEnd; char *string; /* Check if this was the selection request for which this handler was set up, if not, do nothing */ if (event->type != SelectionNotify || e->time != cbInfo->timeStamp) return; /* The time stamp matched, remove this event handler and its backup timer procedure */ XtRemoveEventHandler(w, 0, True, selectNotifyEH, data); XtRemoveTimeOut(cbInfo->timeoutProcID); /* Check if the request succeeded, if not, beep, remove any existing secondary selection, and return */ if (e->property == None) { XBell(XtDisplay(w), 0); BufSecondaryUnselect(buf); XtDisownSelection(w, XA_SECONDARY, e->time); if (cbInfo->actionText != NULL) XtFree((char *)cbInfo->actionText); XtFree((char *)cbInfo); return; } /* Do the requested action, if the action is exchange, also clean up the properties created for returning the primary selection and making the MULTIPLE target request */ if (cbInfo->action == REMOVE_SECONDARY) { BufRemoveSecSelect(buf); } else if (cbInfo->action == EXCHANGE_SECONDARY) { string = XtMalloc(cbInfo->length + 1); memcpy(string, cbInfo->actionText, cbInfo->length); string[cbInfo->length] = '\0'; selStart = buf->secondary.start; if (BufSubstituteNullChars(string, cbInfo->length, buf)) { BufReplaceSecSelect(buf, string); if (buf->secondary.rectangular) { /*... it would be nice to re-select, but probably impossible */ TextDSetInsertPosition(((TextWidget)w)->text.textD, buf->cursorPosHint); } else { selEnd = selStart + cbInfo->length; BufSelect(buf, selStart, selEnd); TextDSetInsertPosition(((TextWidget)w)->text.textD, selEnd); } } else fprintf(stderr, "Too much binary data\n"); XtFree(string); } BufSecondaryUnselect(buf); XtDisownSelection(w, XA_SECONDARY, e->time); if (cbInfo->actionText != NULL) XtFree((char *)cbInfo->actionText); XtFree((char *)cbInfo);}/*** Xt timer procedure for timeouts on XConvertSelection requests, cleans up** after a complete failure of the selection mechanism to return a selection** notify event for a convert selection request*/static void selectNotifyTimerProc(XtPointer clientData, XtIntervalId *id){ selectNotifyInfo *cbInfo = (selectNotifyInfo *)clientData; textBuffer *buf = ((TextWidget)cbInfo->widget)->text.textD->buffer; fprintf(stderr, "NEdit: timeout on selection request\n"); XtRemoveEventHandler(cbInfo->widget, 0, True, selectNotifyEH, cbInfo); BufSecondaryUnselect(buf); XtDisownSelection(cbInfo->widget, XA_SECONDARY, cbInfo->timeStamp); if (cbInfo->actionText != NULL) XtFree((char *)cbInfo->actionText); XtFree((char *)cbInfo);}/*** Maintain a cache of interned atoms. To reference one, use the constant** from the enum, atomIndex, above.*/static Atom getAtom(Display *display, int atomNum){ static Atom atomList[N_ATOMS] = {0}; static char *atomNames[N_ATOMS] = {"TEXT", "TARGETS", "MULTIPLE", "TIMESTAMP", "INSERT_SELECTION", "DELETE", "CLIPBOARD", "INSERT_INFO", "ATOM_PAIR", "MOTIF_DESTINATION", "COMPOUND_TEXT"}; if (atomList[atomNum] == 0) atomList[atomNum] = XInternAtom(display, atomNames[atomNum], False); return atomList[atomNum];}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -