textdrag.c
来自「nedit 是一款linux下的开发源码的功能强大的编辑器」· C语言 代码 · 共 585 行 · 第 1/2 页
C
585 行
not wrapped */ TextDXYToUnconstrainedPosition(textD, max(0, x - dragXOffset), max(0, y - (tw->text.dragYOffset % fontHeight)), &row, &column); column = TextDOffsetWrappedColumn(textD, row, column); row = TextDOffsetWrappedRow(textD, row); insLineNum = row + textD->topLineNum - tw->text.dragYOffset / fontHeight; /* find a common point of reference between the two buffers, from which the insert position line number can be translated to a position */ if (textD->firstChar > modRangeStart) { referenceLine = textD->topLineNum - BufCountLines(buf, modRangeStart, textD->firstChar); referencePos = modRangeStart; } else { referencePos = textD->firstChar; referenceLine = textD->topLineNum; } /* find the position associated with the start of the new line in the temporary buffer */ insLineStart = findRelativeLineStart(tempBuf, referencePos - tempStart, referenceLine, insLineNum) + tempStart; if (insLineStart - tempStart == tempBuf->length) insLineStart = BufStartOfLine(tempBuf, insLineStart - tempStart) + tempStart; /* Find the actual insert position */ if (rectangular || overlay) { insStart = insLineStart; insRectStart = column; } else { /* note, this will fail with proportional fonts */ insStart = BufCountForwardDispChars(tempBuf, insLineStart - tempStart, column) + tempStart; insRectStart = 0; } /* If the position is the same as last time, don't bother drawing (it would be nice if this decision could be made earlier) */ if (insStart == tw->text.dragInsertPos && insRectStart == tw->text.dragRectStart && dragType == oldDragType) { BufFree(tempBuf); return; } /* Do the insert in the temporary buffer */ if (rectangular || overlay) { insText = BufGetTextInRect(origBuf, origSelLineStart, origSelLineEnd, origSel->rectStart, origSel->rectEnd); if (overlay) BufOverlayRect(tempBuf, insStart - tempStart, insRectStart, insRectStart + origSel->rectEnd - origSel->rectStart, insText, &insertInserted, &insertDeleted); else BufInsertCol(tempBuf, insRectStart, insStart - tempStart, insText, &insertInserted, &insertDeleted); trackModifyRange(&modRangeStart, &tempModRangeEnd, &bufModRangeEnd, insStart, insertInserted, insertDeleted); XtFree(insText); } else { insText = BufGetSelectionText(origBuf); BufInsert(tempBuf, insStart - tempStart, insText); trackModifyRange(&modRangeStart, &tempModRangeEnd, &bufModRangeEnd, insStart, origSel->end - origSel->start, 0); insertInserted = origSel->end - origSel->start; insertDeleted = 0; XtFree(insText); } /* Make the changes in the real buffer */ repText = BufGetRange(tempBuf, modRangeStart - tempStart, tempModRangeEnd - tempStart); BufFree(tempBuf); TextDBlankCursor(textD); BufReplace(buf, modRangeStart, bufModRangeEnd, repText); XtFree(repText); /* Store the necessary information for undoing this step */ tw->text.dragInsertPos = insStart; tw->text.dragRectStart = insRectStart; tw->text.dragInserted = insertInserted; tw->text.dragDeleted = insertDeleted; tw->text.dragSourceDeletePos = sourceDeletePos; tw->text.dragSourceInserted = sourceInserted; tw->text.dragSourceDeleted = sourceDeleted; tw->text.dragType = dragType; /* Reset the selection and cursor position */ if (rectangular || overlay) { insRectEnd = insRectStart + origSel->rectEnd - origSel->rectStart; BufRectSelect(buf, insStart, insStart + insertInserted, insRectStart, insRectEnd); TextDSetInsertPosition(textD, BufCountForwardDispChars(buf, BufCountForwardNLines(buf, insStart, tw->text.dragNLines), insRectEnd)); } else { BufSelect(buf, insStart, insStart + origSel->end - origSel->start); TextDSetInsertPosition(textD, insStart + origSel->end - origSel->start); } TextDUnblankCursor(textD); XtCallCallbacks((Widget)tw, textNcursorMovementCallback, (XtPointer)NULL); tw->text.emTabsBeforeCursor = 0;}/*** Complete a block text drag operation*/void FinishBlockDrag(TextWidget tw){ dragEndCBStruct endStruct; int modRangeStart = -1, origModRangeEnd, bufModRangeEnd; char *deletedText; /* Find the changed region of the buffer, covering both the deletion of the selected text at the drag start position, and insertion at the drag destination */ trackModifyRange(&modRangeStart, &bufModRangeEnd, &origModRangeEnd, tw->text.dragSourceDeletePos, tw->text.dragSourceInserted, tw->text.dragSourceDeleted); trackModifyRange(&modRangeStart, &bufModRangeEnd, &origModRangeEnd, tw->text.dragInsertPos, tw->text.dragInserted, tw->text.dragDeleted); /* Get the original (pre-modified) range of text from saved backup buffer */ deletedText = BufGetRange(tw->text.dragOrigBuf, modRangeStart, origModRangeEnd); /* Free the backup buffer */ BufFree(tw->text.dragOrigBuf); /* Return to normal drag state */ tw->text.dragState = NOT_CLICKED; /* Call finish-drag calback */ endStruct.startPos = modRangeStart; endStruct.nCharsDeleted = origModRangeEnd - modRangeStart; endStruct.nCharsInserted = bufModRangeEnd - modRangeStart; endStruct.deletedText = deletedText; XtCallCallbacks((Widget)tw, textNdragEndCallback, (XtPointer)&endStruct); XtFree(deletedText);}/*** Cancel a block drag operation*/void CancelBlockDrag(TextWidget tw){ textBuffer *buf = tw->text.textD->buffer; textBuffer *origBuf = tw->text.dragOrigBuf; selection *origSel = &origBuf->primary; int modRangeStart = -1, origModRangeEnd, bufModRangeEnd; char *repText; dragEndCBStruct endStruct; /* If the operation was a move, make the modify range reflect the removal of the text from the starting position */ if (tw->text.dragSourceDeleted != 0) trackModifyRange(&modRangeStart, &bufModRangeEnd, &origModRangeEnd, tw->text.dragSourceDeletePos, tw->text.dragSourceInserted, tw->text.dragSourceDeleted); /* Include the insert being undone from the last step in the modified range. */ trackModifyRange(&modRangeStart, &bufModRangeEnd, &origModRangeEnd, tw->text.dragInsertPos, tw->text.dragInserted, tw->text.dragDeleted); /* Make the changes in the buffer */ repText = BufGetRange(origBuf, modRangeStart, origModRangeEnd); BufReplace(buf, modRangeStart, bufModRangeEnd, repText); XtFree(repText); /* Reset the selection and cursor position */ if (origSel->rectangular) BufRectSelect(buf, origSel->start, origSel->end, origSel->rectStart, origSel->rectEnd); else BufSelect(buf, origSel->start, origSel->end); TextDSetInsertPosition(tw->text.textD, buf->cursorPosHint); XtCallCallbacks((Widget)tw, textNcursorMovementCallback, NULL); tw->text.emTabsBeforeCursor = 0; /* Free the backup buffer */ BufFree(origBuf); /* Indicate end of drag */ tw->text.dragState = DRAG_CANCELED; /* Call finish-drag calback */ endStruct.startPos = 0; endStruct.nCharsDeleted = 0; endStruct.nCharsInserted = 0; endStruct.deletedText = NULL; XtCallCallbacks((Widget)tw, textNdragEndCallback, (XtPointer)&endStruct);}/*** Maintain boundaries of changed region between two buffers which** start out with identical contents, but diverge through insertion,** deletion, and replacement, such that the buffers can be reconciled** by replacing the changed region of either buffer with the changed** region of the other.**** rangeStart is the beginning of the modification region in the shared** coordinates of both buffers (which are identical up to rangeStart).** modRangeEnd is the end of the changed region for the buffer being** modified, unmodRangeEnd is the end of the region for the buffer NOT** being modified. A value of -1 in rangeStart indicates that there** have been no modifications so far.*/static void trackModifyRange(int *rangeStart, int *modRangeEnd, int *unmodRangeEnd, int modPos, int nInserted, int nDeleted){ if (*rangeStart == -1) { *rangeStart = modPos; *modRangeEnd = modPos + nInserted; *unmodRangeEnd = modPos + nDeleted; } else { if (modPos < *rangeStart) *rangeStart = modPos; if (modPos + nDeleted > *modRangeEnd) { *unmodRangeEnd += modPos + nDeleted - *modRangeEnd; *modRangeEnd = modPos + nInserted; } else *modRangeEnd += nInserted - nDeleted; }}/*** Find the left and right margins of text between "start" and "end" in** buffer "buf". Note that "start is assumed to be at the start of a line. */static void findTextMargins(textBuffer *buf, int start, int end, int *leftMargin, int *rightMargin){ char c; int pos, width = 0, maxWidth = 0, minWhite = INT_MAX, inWhite = True; for (pos=start; pos<end; pos++) { c = BufGetCharacter(buf, pos); if (inWhite && c != ' ' && c != '\t') { inWhite = False; if (width < minWhite) minWhite = width; } if (c == '\n') { if (width > maxWidth) maxWidth = width; width = 0; inWhite = True; } else width += BufCharWidth(c, width, buf->tabDist, buf->nullSubsChar); } if (width > maxWidth) maxWidth = width; *leftMargin = minWhite == INT_MAX ? 0 : minWhite; *rightMargin = maxWidth;}/*** Find a text position in buffer "buf" by counting forward or backward** from a reference position with known line number*/static int findRelativeLineStart(textBuffer *buf, int referencePos, int referenceLineNum, int newLineNum){ if (newLineNum < referenceLineNum) return BufCountBackwardNLines(buf, referencePos, referenceLineNum - newLineNum); else if (newLineNum > referenceLineNum) return BufCountForwardNLines(buf, referencePos, newLineNum - referenceLineNum); return BufStartOfLine(buf, referencePos);}static int min3(int i1, int i2, int i3){ if (i1 <= i2 && i1 <= i3) return i1; return i2 <= i3 ? i2 : i3;}static int max3(int i1, int i2, int i3){ if (i1 >= i2 && i1 >= i3) return i1; return i2 >= i3 ? i2 : i3;}static int max(int i1, int i2){ return i1 >= i2 ? i1 : i2;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?