📄 text.c
字号:
{ TextDGetScroll(((TextWidget)w)->text.textD, topLineNum, horizOffset);}/*** Set the horizontal and vertical scroll positions of the widget*/void TextSetScroll(Widget w, int topLineNum, int horizOffset){ TextDSetScroll(((TextWidget)w)->text.textD, topLineNum, horizOffset);}int TextGetMinFontWidth(Widget w, Boolean considerStyles){ return(TextDMinFontWidth(((TextWidget)w)->text.textD, considerStyles));}int TextGetMaxFontWidth(Widget w, Boolean considerStyles){ return(TextDMaxFontWidth(((TextWidget)w)->text.textD, considerStyles));}/*** Set this widget to be the owner of selections made in it's attached** buffer (text buffers may be shared among several text widgets).*/void TextHandleXSelections(Widget w){ HandleXSelections(w);}void TextStopHandlingSelections(Widget w){ StopHandlingXSelections(w);}void TextPasteClipboard(Widget w, Time time){ cancelDrag(w); if (checkReadOnly(w)) return; TakeMotifDestination(w, time); InsertClipboard(w, False); callCursorMovementCBs(w, NULL);}void TextColPasteClipboard(Widget w, Time time){ cancelDrag(w); if (checkReadOnly(w)) return; TakeMotifDestination(w, time); InsertClipboard(w, True); callCursorMovementCBs(w, NULL);}void TextCopyClipboard(Widget w, Time time){ cancelDrag(w); if (!((TextWidget)w)->text.textD->buffer->primary.selected) { XBell(XtDisplay(w), 0); return; } CopyToClipboard(w, time);}void TextCutClipboard(Widget w, Time time){ textDisp *textD = ((TextWidget)w)->text.textD; cancelDrag(w); if (checkReadOnly(w)) return; if (!textD->buffer->primary.selected) { XBell(XtDisplay(w), 0); return; } TakeMotifDestination(w, time); CopyToClipboard (w, time); BufRemoveSelected(textD->buffer); TextDSetInsertPosition(textD, textD->buffer->cursorPosHint); checkAutoShowInsertPos(w);}int TextFirstVisibleLine(Widget w){ return(((TextWidget)w)->text.textD->topLineNum);}int TextNumVisibleLines(Widget w){ return(((TextWidget)w)->text.textD->nVisibleLines);}int TextVisibleWidth(Widget w){ return(((TextWidget)w)->text.textD->width);}int TextFirstVisiblePos(Widget w){ return ((TextWidget)w)->text.textD->firstChar;}int TextLastVisiblePos(Widget w){ return ((TextWidget)w)->text.textD->lastChar;} /*** Insert text "chars" at the cursor position, respecting pending delete** selections, overstrike, and handling cursor repositioning as if the text** had been typed. If autoWrap is on wraps the text to fit within the wrap** margin, auto-indenting where the line was wrapped (but nowhere else).** "allowPendingDelete" controls whether primary selections in the widget are** treated as pending delete selections (True), or ignored (False). "event"** is optional and is just passed on to the cursor movement callbacks.*/void TextInsertAtCursor(Widget w, char *chars, XEvent *event, int allowPendingDelete, int allowWrap){ int wrapMargin, colNum, lineStartPos, cursorPos; char *c, *lineStartText, *wrappedText; TextWidget tw = (TextWidget)w; textDisp *textD = tw->text.textD; textBuffer *buf = textD->buffer; int fontWidth = textD->fontStruct->max_bounds.width; int replaceSel, singleLine, breakAt = 0; /* Don't wrap if auto-wrap is off or suppressed, or it's just a newline */ if (!allowWrap || !tw->text.autoWrap || (chars[0] == '\n' && chars[1] == '\0')) { simpleInsertAtCursor(w, chars, event, allowPendingDelete); return; } /* If this is going to be a pending delete operation, the real insert position is the start of the selection. This will make rectangular selections wrap strangely, but this routine should rarely be used for them, and even more rarely when they need to be wrapped. */ replaceSel = allowPendingDelete && pendingSelection(w); cursorPos = replaceSel ? buf->primary.start : TextDGetInsertPosition(textD); /* If the text is only one line and doesn't need to be wrapped, just insert it and be done (for efficiency only, this routine is called for each character typed). (Of course, it may not be significantly more efficient than the more general code below it, so it may be a waste of time!) */ wrapMargin = tw->text.wrapMargin != 0 ? tw->text.wrapMargin : textD->width / fontWidth; lineStartPos = BufStartOfLine(buf, cursorPos); colNum = BufCountDispChars(buf, lineStartPos, cursorPos); for (c=chars; *c!='\0' && *c!='\n'; c++) colNum += BufCharWidth(*c, colNum, buf->tabDist, buf->nullSubsChar); singleLine = *c == '\0'; if (colNum < wrapMargin && singleLine) { simpleInsertAtCursor(w, chars, event, True); return; } /* Wrap the text */ lineStartText = BufGetRange(buf, lineStartPos, cursorPos); wrappedText = wrapText(tw, lineStartText, chars, lineStartPos, wrapMargin, replaceSel ? NULL : &breakAt); XtFree(lineStartText); /* Insert the text. Where possible, use TextDInsert which is optimized for less redraw. */ if (replaceSel) { BufReplaceSelected(buf, wrappedText); TextDSetInsertPosition(textD, buf->cursorPosHint); } else if (tw->text.overstrike) { if (breakAt == 0 && singleLine) TextDOverstrike(textD, wrappedText); else { BufReplace(buf, cursorPos-breakAt, cursorPos, wrappedText); TextDSetInsertPosition(textD, buf->cursorPosHint); } } else { if (breakAt == 0) { TextDInsert(textD, wrappedText); } else { BufReplace(buf, cursorPos-breakAt, cursorPos, wrappedText); TextDSetInsertPosition(textD, buf->cursorPosHint); } } XtFree(wrappedText); checkAutoShowInsertPos(w); callCursorMovementCBs(w, event);}/*** Fetch text from the widget's buffer, adding wrapping newlines to emulate** effect acheived by wrapping in the text display in continuous wrap mode.*/char *TextGetWrapped(Widget w, int startPos, int endPos, int *outLen){ textDisp *textD = ((TextWidget)w)->text.textD; textBuffer *buf = textD->buffer; textBuffer *outBuf; int fromPos, toPos, outPos; char c, *outString; if (!((TextWidget)w)->text.continuousWrap || startPos == endPos) { *outLen = endPos - startPos; return BufGetRange(buf, startPos, endPos); } /* Create a text buffer with a good estimate of the size that adding newlines will expand it to. Since it's a text buffer, if we guess wrong, it will fail softly, and simply expand the size */ outBuf = BufCreatePreallocated((endPos-startPos) + (endPos-startPos)/5); outPos = 0; /* Go (displayed) line by line through the buffer, adding newlines where the text is wrapped at some character other than an existing newline */ fromPos = startPos; toPos = TextDCountForwardNLines(textD, startPos, 1, False); while (toPos < endPos) { BufCopyFromBuf(buf, outBuf, fromPos, toPos, outPos); outPos += toPos - fromPos; c = BufGetCharacter(outBuf, outPos-1); if (c == ' ' || c == '\t') BufReplace(outBuf, outPos-1, outPos, "\n"); else if (c != '\n') { BufInsert(outBuf, outPos, "\n"); outPos++; } fromPos = toPos; toPos = TextDCountForwardNLines(textD, fromPos, 1, True); } BufCopyFromBuf(buf, outBuf, fromPos, endPos, outPos); /* return the contents of the output buffer as a string */ outString = BufGetAll(outBuf); *outLen = outBuf->length; BufFree(outBuf); return outString;}/*** Return the (statically allocated) action table for menu item actions.**** Warning: This routine can only be used before the first text widget is** created! After that, apparently, Xt takes over the table and overwrites** it with its own version. XtGetActionList is preferable, but is not** available before X11R5.*/XtActionsRec *TextGetActions(int *nActions){ *nActions = XtNumber(actionsList); return actionsList;}static void grabFocusAP(Widget w, XEvent *event, String *args, Cardinal *nArgs){ XButtonEvent *e = &event->xbutton; TextWidget tw = (TextWidget)w; textDisp *textD = tw->text.textD; Time lastBtnDown = tw->text.lastBtnDown; int row, column; /* Indicate state for future events, PRIMARY_CLICKED indicates that the proper initialization has been done for primary dragging and/or multi-clicking. Also record the timestamp for multi-click processing */ tw->text.dragState = PRIMARY_CLICKED; tw->text.lastBtnDown = e->time; /* Become owner of the MOTIF_DESTINATION selection, making this widget the designated recipient of secondary quick actions in Motif XmText widgets and in other NEdit text widgets */ TakeMotifDestination(w, e->time); /* Check for possible multi-click sequence in progress */ if (tw->text.multiClickState != NO_CLICKS) { if (e->time < lastBtnDown + XtGetMultiClickTime(XtDisplay(w))) { if (tw->text.multiClickState == ONE_CLICK) { selectWord(w, e->x); callCursorMovementCBs(w, event); return; } else if (tw->text.multiClickState == TWO_CLICKS) { selectLine(w); callCursorMovementCBs(w, event); return; } else if (tw->text.multiClickState == THREE_CLICKS) { BufSelect(textD->buffer, 0, textD->buffer->length); return; } else if (tw->text.multiClickState > THREE_CLICKS) tw->text.multiClickState = NO_CLICKS; } else tw->text.multiClickState = NO_CLICKS; } /* Clear any existing selections */ BufUnselect(textD->buffer); /* Move the cursor to the pointer location */ moveDestinationAP(w, event, args, nArgs); /* Record the site of the initial button press and the initial character position so subsequent motion events and clicking can decide when and where to begin a primary selection */ tw->text.btnDownX = e->x; tw->text.btnDownY = e->y; tw->text.anchor = TextDGetInsertPosition(textD); TextDXYToUnconstrainedPosition(textD, e->x, e->y, &row, &column); column = TextDOffsetWrappedColumn(textD, row, column); tw->text.rectAnchor = column;}static void moveDestinationAP(Widget w, XEvent *event, String *args, Cardinal *nArgs){ XButtonEvent *e = &event->xbutton; textDisp *textD = ((TextWidget)w)->text.textD; /* Get input focus */ XmProcessTraversal(w, XmTRAVERSE_CURRENT); /* Move the cursor */ TextDSetInsertPosition(textD, TextDXYToPosition(textD, e->x, e->y)); checkAutoShowInsertPos(w); callCursorMovementCBs(w, event);}static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -