📄 term.c
字号:
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 + -