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 + -
显示快捷键?