⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 term.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 5 页
字号:
static void selectInvalidate(int y1, int x1, int y2, int x2)
{
    int swap;			/* temporary */
    RECT rect;			/* build window rect to invalidate */

    /* Make sure that (y1,x1) is before (y2,x2)
     */
    if (y1 > y2) {
	swap = y1;
	y1 = y2;
	y2 = swap;
	swap = x1;
	x1 = x2;
	x2 = swap;
    } else if (y1 == y2 && x1 > x2) {
	swap = x1;
	x1 = x2;
	x2 = swap;
    }

    /* Convert y1, y2 to window lines
     */
    y1 -= term.topVisibleLine;
    y2 -= term.topVisibleLine;

    /* Be really gutless and only invalidate lines
     */

    if (y1==y2) {
	rect.top = y1 * term.charSize.cy;
	rect.bottom = (y2 + 1) * term.charSize.cy;
	rect.left = x1 * term.charSize.cx;
	rect.right = x2 * term.charSize.cx;

    } else {
	rect.top = y1 * term.charSize.cy;
	rect.bottom = (y2 + 1) * term.charSize.cy;
	rect.left = 0;
	rect.right = term.winSize.cx * term.charSize.cx;

    }

    InvalidateRect(termWnd, &rect, FALSE);
}

/* Check if an area overlaps with the selection.  If it does, erase
 * the selection.
 *
 * Args:
 * y1 - line index of selection start
 * x1 - column number of selection start
 * y2 - line index of selection end
 * x2 - column number of selection end
 */
static void selectCheckOverlap(int y1, int x1, int y2, int x2)
{
    int yTop;			/* top of overlapping region */
    int yBottom;		/* bottom of overlapping region */

    if (!term.haveSelection)
	/* No selection, cannot overlap
	 */
	return;

    /* Determine the top and bottom lines that overlap
     */
    yTop =    max(y1, (int)term.selectFrom.y);
    yBottom = min(y2, (int)term.selectTo.y);
    if (yTop > yBottom)
	/* No overlapping region, nothing to do
	 */
	return;

    if (yTop != y1)
	/* The overlap was not on the first line of the area.
	 * Subsequent lines in the area MUST start at column 0.
	 */
	x1 = 0;
    if (yBottom != y2)
	/* The overlap was not on the last line of the area.  Previous
	 * lines MUST end at the last column.
	 */
	x2 = term.winSize.cx;

    if (y1 == y2) {
	/* Start and end of the overlap are on the same line.
	 * Determine if there is an overlap on that line.
	 */
	if (x1 < term.selectFrom.x) x1 = term.selectFrom.x;
	if (x2 > term.selectTo.x)   x2 = term.selectTo.x;
	if (x1 >= x2)
	    /* No overlap, nothing else to do.
	     */
	    return;
    }

    /* There is an overlap between the area and the selection.  Cancel
     * the selection.
     */
    selectInvalidate(term.selectFrom.y, term.selectFrom.x,
		     term.selectTo.y, term.selectTo.x);
    term.haveSelection = FALSE;
}

/* Paste the current clipboard contents into the terminal
 */
void termSelectPaste()
{
    /* Get text from the clipboard
     */
    if (OpenClipboard(termWnd)) {
	HANDLE clipHnd;		/* handle to text clipboard data */
	LPSTR text;		/* point to text on clipboard */
	DWORD size;		/* size of text on clipboard */
	size_t len;

	if ((clipHnd = GetClipboardData(CF_TEXT))==NULL) {
	    /* No text on clipboard
	     */
	    CloseClipboard();
	    return;
	}

	if ((text = (LPSTR)GlobalLock(clipHnd))==NULL) {
	    /* Could not get access to the clipboard text
	     */
	    CloseClipboard();
	    return;
	}

	/* Find the size of the clipboard text and then send it to the
	 * remote end
	 */
	size = GlobalSize(clipHnd);
	if (size != 0 && size < INT_MAX)
	{
	    /* --- Paste problem identified by toomus vv
	     * break the text into smaller chunks
	     * (this helps if there's a bunch of text to transfer in
	     *   the clipboard)
	     */
	    /* --- Direct sending commented out by LZS on 2002.01.04.
	     * reasons: - local echo
	     *          - charset conversion
	     */
	    len = strlen (text);
	    /* 2002.01.09 by Enrique Grandes
	     * translate '\r\n' into '\r' for emulKeyPress()
	     */
	    if (!socketConnected() || term.echoKeystrokes) {
		/* When in local echo mode, or not connected,
		   echo the characters
		 */
		emulAddText((unsigned char*)(text), len, TRUE);

	    } else if (socketConnected()) {
		size_t offset = 0;
		size_t chunk_length = 4096;

		while (offset < len) {
		    size_t bytes_remaining = len - offset;

		    if (chunk_length > bytes_remaining)
			chunk_length = bytes_remaining;

		    socketWrite(text+offset, chunk_length);
		    offset += chunk_length;
		}
	    }
	}

	/* Clean up
	 */
	GlobalUnlock(clipHnd);
	CloseClipboard();
    }
}

/* termGetChar: rutin of termSelectGetText
 * before the very first call set
 * *nChar=0, *cf=DTCHAR_ASCII (or the desired format)
 * after the very last call
 * *nChar=number of characters, *cf=DTCHAR_xxx
 */

void termGetChars (char *text, const DtChar *ch, int len, int *nChar, int *cs)
{
    int i, csnow;

    for (i=0; i<len; ++i) {
	csnow = ch[i].cType; /* DTCHAR_xxx */
        if (*cs==DTCHAR_ASCII) { /* cs not defined yet, define it to the current */
	    *cs = csnow;
	    if (text) text[*nChar] = ch[i].cCode;
        } else if (csnow==*cs) { /* match */
	    if (text) text[*nChar] = ch[i].cCode;
        } else { /* convert */
	    if (text) {
		text[*nChar] = ch[i].cCode;
		if (csnow==DTCHAR_OEM) OemToAnsiBuff (&text[*nChar], &text[*nChar], 1);
		else                AnsiToOemBuff (&text[*nChar], &text[*nChar], 1);
	    }
        }
        ++*nChar;
    }
}

/* Similar to the previous, but for constant characters
 * which are CF-independent (code 0..127)
 */
void termGetConstChars (char *text, const char *ch, int len, int *nChar)
{
    int i;

    for (i=0; i<len; ++i) {
	if (text) text[*nChar] = ch[i];
        ++*nChar;
    }
}

/* Copy the selected text into the specified buffer
 *
 * Args:
 * text - pointer to buffer large enough to hold the selection.  If
 *	NULL, the function does not copy data, it just calculates the
 *	size of the buffer needed to hold the selection.
 * cs - returns DTCHAR_xxx
 *
 * Returns the size of data in the selection
 */
static DWORD termSelectGetText(char* text, int *cs)
{
    POINT start;		/* start of the selection */
    POINT end;			/* end of the selection */
    int  size = 0;		/* calculate size of the selection */
    int lineNum;		/* iterate over lines in selection */

    *cs = DTCHAR_ASCII;             /* not defined yet */
    /* Get start and end of the selection
     */
    termSelectGetRange(&start, &end);

    /* Iterate over all lines in the selection
     */
    for (lineNum = start.y; lineNum <= end.y; ++lineNum) {
	Line* line = linesGetLine(lineNum);

	if (line == NULL)
	    /* Just in case
	     */
	    break;

	if (start.x >= line->len) {
	    /* Starting at or after end of line - copy \r\n
	     */
	    if (!line->wrapped) {
		termGetConstChars (text, "\r\n", 2, &size);
	    }
	} else {
			/* Work out how much text to get from line
	     */
	    if (lineNum < end.y || end.x > line->len) {
		/* Copying past end of line - include \r\n
		 */
		termGetChars (text, line->text + start.x, line->len - start.x, &size, cs);
		if (!line->wrapped) {
		    termGetConstChars (text, "\r\n", 2, &size);
		}

	    } else {
		/* Only copying part of a line
		 */
		termGetChars (text, line->text + start.x, end.x - start.x, &size, cs);
	    }
	}

	/* When moving to next line, reset column
	 */
	start.x = 0;
    }
    termGetConstChars (text, "\0", 1, &size);

    return size;		/* including trailing nul */
}

/* Copy the selection onto the clipboard
 */
void termSelectCopy(void)
{
    DWORD size;			/* size of data in the selection */
    HGLOBAL textHnd;		/* allocate memory to hold selection */
    void* text;			/* point to allocated memory */
    int cs, cf;

    /* Find the size of the selection, then allocate enough memory to
     * hold it
     */
    size = termSelectGetText(NULL, &cs);
    if ((textHnd = GlobalAlloc(GMEM_MOVEABLE, size))==NULL)
	return;
    if ((text = GlobalLock(textHnd))==NULL)
	return;

    /* Copy the selection into the allocated memory
     */
    termSelectGetText((char *)text, &cs);
    if (cs==DTCHAR_OEM) cf = CF_OEMTEXT;
    else                cf = CF_TEXT;

    GlobalUnlock(textHnd);

    /* Clear the current contents of the clipboard, and set the text
     * handle to the new text.
     */
    if (OpenClipboard(termWnd)) {
	EmptyClipboard();
	SetClipboardData(cf, textHnd); /* LZS 2004.10.27: format is variable */
	CloseClipboard();
    }
}

/* Set selection mode to characters
 */
static void termSelectCharMode(void)
{
    term.selectWords = FALSE;
}

/* Set selection mode to words
 */
static void termSelectWordMode(void)
{
    term.selectWords = TRUE;
}

/* Extend the selection to the start/end of the current word if
 * necessary
 *
 * Args:
 * xpos -       point to column that mouse pointer is in
 * ypos -       point to index of line mouse pointer is in
 * inNextChar - is mouse pointer in the next character position to right?
 */
static void termSelectWordExtend(int* xpos, int* ypos, BOOL inNextChar)
{
    Line* line;			/* line the mouse pointer is in */

    if (!term.selectWords)
	/* Not selecting words - nothing to do
	 */
	return;

    line = linesGetLine(*ypos);
    if (line == NULL)
	/* Just in case
	 */
	return;

    if (*ypos > term.selectFrom.y
	|| *ypos == term.selectFrom.y && *xpos >= term.selectFrom.x) {
	/* Mouse is in front of selectFrom.  Extend selection forwards.
	 */
	if (inNextChar) {
	    /* Mouse is in next character cell, extend xpos forwards
	     * to next word boundary
	     */
	    if (*xpos < line->len) {
		/* Selection point is in line, scan over word
		 */
		if (isalnum(line->text[*xpos].cCode)) {  /* <FIXME> */
		    while (*xpos < line->len && isalnum(line->text[*xpos + 1].cCode))
			++*xpos;
		}
		/* Extend xpos to include word
		 */
		if (*xpos < line->len)
		    ++*xpos;
	    } else
		/* Selection point is past end of line.  Extend
		 * forwards to next character cell (where mouse is)
		 */
		++*xpos;
	}
    } else {
	/* This point is behind selectFrom.  Extend selection
	 * backwards
	 */
	if (isalnum(line->text[*xpos].cCode))
	    while (*xpos > 0 && isalnum(line->text[*xpos - 1].cCode))
		--*xpos;
    }
}

/* Extend the selection to the specified position
 *
 * Args:
 * xpos -       column that mouse is in
 * ypos -       terminal line that mouse is in
 * inNextChar - is the mouse over the next character cell?
 */
static void termSelectExtend(int xpos, int ypos, BOOL inNextChar)
{
    /* We now have a selection
     */
    term.haveSelection = TRUE;

    /* Convert ypos to a line index
     */
    ypos += term.topVisibleLine;

    /* Adjust the selection when select mode is words
     */
		termSelectWordExtend(&xpos, &ypos, inNextChar);
    if (xpos == term.selectTo.x && ypos == term.selectTo.y)
	/* No change in the selection, nothing else to do
	 */
	return;

    /* Get Windows to update the changed area of the terminal window
     */
    selectInvalidate(term.selectTo.y, term.selectTo.x, ypos, xpos);
    /* Update selection range
     */
    term.selectTo.x = xpos;
    term.selectTo.y = ypos;
}

/* Start a new selection at the specified terminal position
 *
 * Args:
 * xpos - column to start selection in
 * ypos - terminal line to start the selection in
 */
static void termSelectStart(int xpos, int ypos)
{
    if (term.haveSelection) {
	/* If we already have a selection, get windows to redraw that
	 * area, and cancel that selection
	 */
	selectInvalidate(term.selectFrom.y, term.selectFrom.x,
			 term.selectTo.y, term.selectTo.x);
	term.haveSelection = FALSE;
    }

		/* Convert ypos from terminal line to line array index
     */
    ypos += term.topVisibleLine;

    /* Reset selection range
     */
    term.selectFrom.x = term.selectTo.x = xpos;
    term.selectFrom.y = term.selectTo.y = ypos;

    if (term.selectWords) {
	/* Selecting words - extend the selection backwards and
	 * forwards to include the current word
	 */
	POINT tmp;		/* swap selectFrom/selectTo */

	/* When selecting words, we have a selection immediately.
	 */
	term.haveSelection = TRUE;

	/* Move selectFrom to next character to force extend backwards
	 */
	term.selectFrom.x++;
	termSelectWordExtend((int *)&term.selectTo.x,
			     (int *)&term.selectTo.y, FALSE);

	/* Swap selectFrom and selectTo, then try to extend forwards
	 */
	tmp = term.selectFrom;
	term.selectFrom = term.selectTo;
	term.selectTo = tmp;
	termSelectWordExtend((int *)&term.selectTo.x,
			     (int *)&term.selectTo.y, TRUE);

	/* Get windows to draw our new selection
	 */
	selectInvalidate(term.selectFrom.y, term.selectFrom.x,
			 term.selectTo.y, term.selectTo.x);
    }
}

/* Finish the selection at the specified position
 *
 * Args:
 * xpos -       column that mouse is in
 * ypos -       terminal line that mouse is in
 * inNextChar - is the mouse over the next character cell?
 */
static void termSelectEnd(int xpos, int ypos, BOOL inNextChar)
{
    /* Convert ypos from terminal line to line array index
     */
    ypos += term.topVisibleLine;
    /* Extend the selection over the next word if necessary

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -