📄 textsel.c
字号:
return; } string[retLength] = '\0'; /* If the string contains ascii-nul characters, substitute something else, or give up, warn, and refuse */ if (!BufSubstituteNullChars(string, retLength, buf)) { fprintf(stderr, "Too much binary data, text not pasted\n"); XtFree(string); return; } /* Insert it in the text widget */ if (isColumnar && !buf->primary.selected) { cursorPos = TextDGetInsertPosition(textD); cursorLineStart = BufStartOfLine(buf, cursorPos); column = BufCountDispChars(buf, cursorLineStart, cursorPos); if (((TextWidget)w)->text.overstrike) { BufOverlayRect(buf, cursorLineStart, column, -1, string, NULL, NULL); } else { BufInsertCol(buf, column, cursorLineStart, string, NULL, NULL); } TextDSetInsertPosition(textD, BufCountForwardDispChars(buf, cursorLineStart, column)); if (((TextWidget)w)->text.autoShowInsertPos) TextDMakeInsertPosVisible(textD); } else TextInsertAtCursor(w, string, NULL, True, ((TextWidget)w)->text.autoWrapPastedText); XtFree(string);}/*** Take ownership of the MOTIF_DESTINATION selection. This is Motif's private** selection type for designating a widget to receive the result of** secondary quick action requests. The NEdit text widget uses this also** for compatibility with Motif text widgets.*/void TakeMotifDestination(Widget w, Time time){ if (((TextWidget)w)->text.motifDestOwner || ((TextWidget)w)->text.readOnly) return; /* Take ownership of the MOTIF_DESTINATION selection */ if (!XtOwnSelection(w, getAtom(XtDisplay(w), A_MOTIF_DESTINATION), time, convertMotifDestCB, loseMotifDestCB, NULL)) { return; } ((TextWidget)w)->text.motifDestOwner = True;}/*** This routine is called every time there is a modification made to the** buffer to which this callback is attached, with an argument of the text** widget that has been designated (by HandleXSelections) to handle its** selections. It checks if the status of the selection in the buffer** has changed since last time, and owns or disowns the X selection depending** on the status of the primary selection in the buffer. If it is not allowed** to take ownership of the selection, it unhighlights the text in the buffer** (Being in the middle of a modify callback, this has a somewhat complicated** result, since later callbacks will see the second modifications first).*/static void modifiedCB(int pos, int nInserted, int nDeleted, int nRestyled, char *deletedText, void *cbArg){ TextWidget w = (TextWidget)cbArg; Time time = XtLastTimestampProcessed(XtDisplay((Widget)w)); int selected = w->text.textD->buffer->primary.selected; int isOwner = w->text.selectionOwner; /* If the widget owns the selection and the buffer text is still selected, or if the widget doesn't own it and there's no selection, do nothing */ if ((isOwner && selected) || (!isOwner && !selected)) return; /* If we own the selection and the selection is now empty, give it up */ if (isOwner && !selected) { XtDisownSelection((Widget)w, XA_PRIMARY, time); w->text.selectionOwner = False; return; } /* Take ownership of the selection */ if (!XtOwnSelection((Widget)w, XA_PRIMARY, time, convertSelectionCB, loseSelectionCB, NULL)) BufUnselect(w->text.textD->buffer); else w->text.selectionOwner = True;}/*** Send an INSERT_SELECTION request to "sel".** Upon completion, do the action specified by "action" (one of enum** selectNotifyActions) using "actionText" and freeing actionText (if** not NULL) when done.*/static void sendSecondary(Widget w, Time time, Atom sel, int action, char *actionText, int actionTextLen){ static Atom selInfoProp[2] = {XA_SECONDARY, XA_STRING}; Display *disp = XtDisplay(w); selectNotifyInfo *cbInfo; XtAppContext context = XtWidgetToApplicationContext((Widget)w); /* Take ownership of the secondary selection, give up if we can't */ if (!XtOwnSelection(w, XA_SECONDARY, time, convertSecondaryCB, loseSecondaryCB, NULL)) { BufSecondaryUnselect(((TextWidget)w)->text.textD->buffer); return; } /* Set up a property on this window to pass along with the INSERT_SELECTION request to tell the MOTIF_DESTINATION owner what selection and what target from that selection to insert */ XChangeProperty(disp, XtWindow(w), getAtom(disp, A_INSERT_INFO), getAtom(disp, A_ATOM_PAIR), 32, PropModeReplace, (unsigned char *)selInfoProp, 2 /* 1? */); /* Make INSERT_SELECTION request to the owner of selection "sel" to do the insert. This must be done using XLib calls to specify the property with the information about what to insert. This means it also requires an event handler to see if the request succeeded or not, and a backup timer to clean up if the select notify event is never returned */ XConvertSelection(XtDisplay(w), sel, getAtom(disp, A_INSERT_SELECTION), getAtom(disp, A_INSERT_INFO), XtWindow(w), time); cbInfo = (selectNotifyInfo *)XtMalloc(sizeof(selectNotifyInfo)); cbInfo->action = action; cbInfo->timeStamp = time; cbInfo->widget = (Widget)w; cbInfo->actionText = actionText; cbInfo->length = actionTextLen; XtAddEventHandler(w, 0, True, selectNotifyEH, (XtPointer)cbInfo); cbInfo->timeoutProcID = XtAppAddTimeOut(context, XtAppGetSelectionTimeout(context), selectNotifyTimerProc, (XtPointer)cbInfo);}/*** Called when data arrives from a request for the PRIMARY selection. If** everything is in order, it inserts it at the cursor in the requesting** widget.*/static void getSelectionCB(Widget w, XtPointer clientData, Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format){ textDisp *textD = ((TextWidget)w)->text.textD; int isColumnar = *(int *)clientData; int cursorLineStart, cursorPos, column, row; char *string; /* Confirm that the returned value is of the correct type */ if (*type != XA_STRING || *format != 8) { if (value != NULL) XtFree((char *)value); return; } /* Copy the string just to make space for the null character (this may not be necessary, XLib documentation claims a NULL is already added, but the Xt documentation for this routine makes no such claim) */ string = XtMalloc(*length + 1); memcpy(string, (char *)value, *length); string[*length] = '\0'; /* If the string contains ascii-nul characters, substitute something else, or give up, warn, and refuse */ if (!BufSubstituteNullChars(string, *length, textD->buffer)) { fprintf(stderr, "Too much binary data, giving up\n"); XtFree(string); XtFree((char *)value); return; } /* Insert it in the text widget */ if (isColumnar) { cursorPos = TextDGetInsertPosition(textD); cursorLineStart = BufStartOfLine(textD->buffer, cursorPos); TextDXYToUnconstrainedPosition(textD, ((TextWidget)w)->text.btnDownX, ((TextWidget)w)->text.btnDownY, &row, &column); BufInsertCol(textD->buffer, column, cursorLineStart, string, NULL,NULL); TextDSetInsertPosition(textD, textD->buffer->cursorPosHint); } else TextInsertAtCursor(w, string, NULL, False, ((TextWidget)w)->text.autoWrapPastedText); XtFree(string); /* The selection requstor is required to free the memory passed to it via value */ XtFree((char *)value);}/*** Called when data arrives from request resulting from processing an** INSERT_SELECTION request. If everything is in order, inserts it at** the cursor or replaces pending delete selection in widget "w", and sets** the flag passed in clientData to SUCCESSFUL_INSERT or UNSUCCESSFUL_INSERT** depending on the success of the operation.*/static void getInsertSelectionCB(Widget w, XtPointer clientData,Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format){ textBuffer *buf = ((TextWidget)w)->text.textD->buffer; char *string; int *resultFlag = (int *)clientData; /* Confirm that the returned value is of the correct type */ if (*type != XA_STRING || *format != 8 || value == NULL) { if (value != NULL) XtFree((char *)value); *resultFlag = UNSUCCESSFUL_INSERT; return; } /* Copy the string just to make space for the null character */ string = XtMalloc(*length + 1); memcpy(string, (char *)value, *length); string[*length] = '\0'; /* If the string contains ascii-nul characters, substitute something else, or give up, warn, and refuse */ if (!BufSubstituteNullChars(string, *length, buf)) { fprintf(stderr, "Too much binary data, giving up\n"); XtFree(string); XtFree((char *)value); return; } /* Insert it in the text widget */ TextInsertAtCursor(w, string, NULL, True, ((TextWidget)w)->text.autoWrapPastedText); XtFree(string); *resultFlag = SUCCESSFUL_INSERT; /* This callback is required to free the memory passed to it thru value */ XtFree((char *)value);}/*** Called when data arrives from an X primary selection request for the** purpose of exchanging the primary and secondary selections.** If everything is in order, stores the retrieved text temporarily and** initiates a request to replace the primary selection with this widget's** secondary selection.*/static void getExchSelCB(Widget w, XtPointer clientData, Atom *selType, Atom *type, XtPointer value, unsigned long *length, int *format){ /* Confirm that there is a value and it is of the correct type */ if (*length == 0 || value == NULL || *type != XA_STRING || *format != 8) { if (value != NULL) XtFree((char *)value); XBell(XtDisplay(w), 0); BufSecondaryUnselect(((TextWidget)w)->text.textD->buffer); return; } /* Request the selection owner to replace the primary selection with this widget's secondary selection. When complete, replace this widget's secondary selection with text "value" and free it. */ sendSecondary(w, XtLastTimestampProcessed(XtDisplay(w)), XA_PRIMARY, EXCHANGE_SECONDARY, (char *)value, *length);}/*** Selection converter procedure used by the widget when it is the selection** owner to provide data in the format requested by the selection requestor.**** Note: Memory left in the *value field is freed by Xt as long as there is no** done_proc procedure registered in the XtOwnSelection call where this** procdeure is registered*/static Boolean convertSelectionCB(Widget w, Atom *selType, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format){ XSelectionRequestEvent *event = XtGetSelectionRequest(w, *selType, 0); textBuffer *buf = ((TextWidget)w)->text.textD->buffer; Display *display = XtDisplay(w); Atom *targets, dummyAtom; unsigned long nItems, dummyULong; Atom *reqAtoms; int getFmt, result = INSERT_WAITING; XEvent nextEvent; /* target is text, string, or compound text */ if (*target == XA_STRING || *target == getAtom(display, A_TEXT) || *target == getAtom(display, A_COMPOUND_TEXT)) { /* We really don't directly support COMPOUND_TEXT, but recent versions gnome-terminal incorrectly ask for it, even though don't declare that we do. Just reply in string format. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -