📄 emul.c
字号:
ASSERT (line->len > 0);
term.cursor.x = line->len - 1;
--term.cursor.y;
if (bKeyboard)
emulCharDeleteCore (1, bKeyboard);
}
}
/* Send the current logical line to the remote end */
static void emulSendCurrentLine(void)
{
int lineIdx;
Line *line, *pline;
int loop;
char LineBuff [sizeof (line->text)];
static const char sCRLF [2] = "\r\n";
int nChar, cs;
const unsigned char *ctmap;
lineIdx = linesTerminalToLine(term.cursor.y);
linesCreateTo(lineIdx);
line = linesGetLine(lineIdx);
if (currEmul.fAnsi) {
cs = DTCHAR_ANSI;
ctmap = currEmul.ctAnsiToServer;
} else {
cs = DTCHAR_OEM;
ctmap = currEmul.ctOemToServer;
}
while (lineIdx > 0 &&
(pline = linesGetLine(lineIdx-1))->wrapped) {
--lineIdx;
--term.cursor.y;
line = pline;
}
for (loop = 1; loop;) {
if (line->len) {/* do not send empty line */
memcpy (LineBuff, line->text, line->len);
nChar = 0;
termGetChars (LineBuff, line->text, line->len, &nChar, &cs);
ctabTranslay (ctmap, LineBuff, line->len);
socketWrite (LineBuff, line->len);
}
if (! line->wrapped) loop = 0;
else {
++lineIdx;
line = linesGetLine(lineIdx);
++term.cursor.y;
}
}
socketWrite (sCRLF, sizeof (sCRLF));
logSession (sCRLF, sizeof (sCRLF));
++term.cursor.y;
term.cursor.x = 0;
emulCursorCheck ();
}
/* Save the current cursor position and character attributes
*/
static void emulCursorSave(void)
{
term.savedCursor = term.cursor;
term.savedAttr = term.currAttr;
term.savedCharSet = term.charSet;
term.savedG0CharSet = term.G0CharSet;
term.savedG1CharSet = term.G1CharSet;
term.savedInverseVideo = term.inverseVideo;
}
/* Restore the previously save cursor position and character attributes
*/
static void emulCursorRestore(void)
{
term.cursor = term.savedCursor;
term.currAttr = term.savedAttr;
term.charSet = term.savedCharSet;
term.G0CharSet = term.savedG0CharSet;
term.G1CharSet = term.savedG1CharSet;
term.inverseVideo = term.savedInverseVideo;
}
/* Perform a reverse line feed. Scroll the terminal down if necessary.
*/
static void emulReverseLineFeed(void)
{
term.cursor.y--;
emulCursorCheck();
}
/* Make sure that the cursor location is within the specifed bounds
*/
static void checkCursorLimits(void)
{
if (term.cursorRelative && term.haveRegion) {
if (term.cursor.y < term.scrollTop)
term.cursor.y = term.scrollTop;
if (term.cursor.y >= term.scrollBottom)
term.cursor.y = term.scrollBottom - 1;
} else {
if (term.cursor.y < 0)
term.cursor.y = 0;
if (term.cursor.y >= term.winSize.cy)
term.cursor.y = term.winSize.cy - 1;
}
if (term.cursor.x < 0)
term.cursor.x = 0;
if (term.cursor.x >= term.winSize.cx)
term.cursor.x = term.winSize.cx - 1;
}
/* Move the cursor to the position y = <param-0>, x = <param-1>. The
* top-left position is 1,1 on the terminal, but 0,0 in all variables.
* If a parameter was missing, a value of 0 is assumed.
*/
static void emulCursorAddress(void)
{
if (term.numParams == 2) {
if (term.params[0] > 0)
term.params[0]--;
if (term.params[1] > 0)
term.params[1]--;
} else if (term.numParams == 0)
term.params[0] = term.params[1] = 0;
else
return;
if (term.cursorRelative && term.haveRegion)
term.params[0] += term.scrollTop;
term.cursor.y = term.params[0];
term.cursor.x = term.params[1];
checkCursorLimits();
}
/* Define a scroll region; top = <param-0> to bottom = <param-1>. If
* top and bottom are 0, cancel any previously defined scroll
* region.
*/
static void emulScrollRegion(void)
{
if (term.numParams != 0 && term.numParams != 2)
return;
if (term.numParams == 0)
term.params[0] = term.params[1] = 0;
if (term.params[0] == 0 && term.params[1] == 0
|| term.params[0] == 1 && term.params[1] == term.winSize.cy) {
/* Cancel scroll region
*/
term.scrollTop = 0;
term.scrollBottom = term.winSize.cy;
term.haveRegion = FALSE;
return;
}
/* Make sure top line is at least 1, and bottom is greater than
* top and on the screen.
*/
if (term.params[0] == 0)
term.params[0] = 1;
if (term.params[0] >= term.params[1] || term.params[1] > term.winSize.cy)
return;
/* Define the new scroll region
*/
term.scrollTop = term.params[0] - 1;
term.scrollBottom = term.params[1];
term.haveRegion = TRUE;
checkCursorLimits();
}
/* Move the cursor to the column defined in <param-0>
*/
static void emulColumnAddress(void)
{
if (term.numParams == 1)
term.cursor.x = term.params[0] == 0 ? 0 : term.params[0] - 1;
checkCursorLimits();
}
/* Move the cursor to the row defined in <param-0>
*/
static void emulRowAddress(void)
{
if (term.numParams == 0)
term.params[0] = 0;
else if (term.numParams != 1)
return;
if (term.params[0] > 0)
term.params[0]--;
if (term.cursorRelative && term.haveRegion)
term.params[0] += term.scrollTop;
term.cursor.y = term.params[0];
checkCursorLimits();
}
/* Insert <param-0> lines at the cursor location. If param-0 was not
* supplied, insert one line.
*/
static void emulLineInsert(void)
{
int numLines; /* number of lines to insert */
if (term.numParams == 0)
numLines = 1;
else if (term.numParams == 1)
numLines = term.params[0];
else
return;
/* There is no point inserting more lines than are on the terminal
*/
if (term.cursor.y + numLines >= term.scrollBottom)
numLines = term.scrollBottom - term.cursor.y;
/* Insert blank lines into line array and terminal window
*/
linesInsert(term.cursor.y, term.scrollBottom, numLines);
winLinesInsert(term.cursor.y, term.scrollBottom, numLines);
}
/* Delete <param-0> lines at the cursor position. If param-0 was not
* specified, delete one line.
*/
static void emulLineDelete(void)
{
int numLines; /* number of lines to delete */
if (term.numParams == 0)
numLines = 1;
else if (term.numParams == 1)
numLines = term.params[0];
else
return;
/* No point deleting more lines than are on the terminal
*/
if (term.cursor.y + numLines >= term.scrollBottom)
numLines = term.scrollBottom - term.cursor.y;
/* Delete lines from the line array and terminal window
*/
linesDelete(term.cursor.y, term.scrollBottom, numLines);
winLinesDelete(term.cursor.y, term.scrollBottom, numLines);
}
/* Insert <param-0> blank characters at the cursor position. If
* param-0 was not supplied, insert one character.
*/
static void emulCharInsert(void)
{
int numChars; /* number of characters to insert */
if (term.numParams == 0)
numChars = 1;
else if (term.numParams == 1)
numChars = term.params[0];
else
return;
/* Insert characters into line array and terminal window
*/
linesCharsInsert(term.cursor.y, term.cursor.x, numChars);
winCharsInsert(term.cursor.y, term.cursor.x);
}
/* Delete n characters at the cursor position.
* If 'bKeyboard' then handle wrapped lines
*/
static void emulCharDeleteCore (int numChars, BOOL bKeyboard)
{
int lineIdx, nlIdx;
Line *line, *nl;
int y, x, yorig, xorig;
int nDelChar, nLineRest, nCpyChar;
y = term.cursor.y;
x = term.cursor.x;
yorig = y;
xorig = x;
lineIdx = linesTerminalToLine(term.cursor.y);
linesCreateTo(lineIdx);
line = linesGetLine(lineIdx);
if (line->len <= x) return;
nDelChar = numChars;
nLineRest = line->len - x;
nDelChar = (nDelChar<=nLineRest) ? numChars : nLineRest;
nCpyChar = nLineRest - nDelChar;
if (nCpyChar > 0) {
memmove(line->text + x, line->text + x + numChars, nCpyChar * sizeof (line->text[0]));
memmove(line->attr + x, line->attr + x + numChars, nCpyChar);
}
line->len -= nDelChar;
if (bKeyboard) { /* 20060426: only if local */
while (line->wrapped) {
nlIdx = lineIdx + 1;
linesCreateTo (nlIdx);
nl = linesGetLine (nlIdx);
nDelChar = (nDelChar <= nl->len) ? nDelChar : nl->len;
nCpyChar = nl->len - nDelChar;
if (nDelChar>0) {
memmove (line->text + line->len, nl->text, nDelChar * sizeof (line->text[0]));
memmove (line->attr + line->len, nl->attr, nDelChar);
line->len += nDelChar;
nl->len -= nDelChar;
if (nl->len==0 && !nl->wrapped) {
line->wrapped = 0;
}
memmove (nl->text, nl->text + nDelChar, nCpyChar * sizeof (line->text[0]));
memmove (nl->attr, nl->attr + nDelChar, nCpyChar);
}
y = y+1;
x = 0;
lineIdx = nlIdx;
line = nl;
}
}
if (y != yorig) {
winModifyRange (yorig, 0, y, term.winSize.cx);
} else {
winModifyRange (yorig, xorig, y, term.winSize.cx);
}
}
/* Delete <param-0> characters at the cursor position. If param-0 was
* not supplied, delete one character.
*/
static void emulCharDelete(BOOL bKeyboard)
{
int numChars; /* number of characters to delete */
if (term.numParams == 0)
numChars = 1;
else if (term.numParams != 1)
return;
else
numChars = term.params[0];
emulCharDeleteCore (numChars, bKeyboard);
}
/* Blank <param-0> characters from the current cursor position. If
* param-0 was not supplied, blank one character.
*/
static void emulCharBlank(void)
{
int numChars; /* number of characters to blank */
if (term.numParams == 0)
numChars = 1;
else if (term.numParams == 1)
numChars = term.params[0];
else
return;
/* Blank characters from the line array and terminal window
*/
linesClearRange(term.cursor.y, term.cursor.x,
term.cursor.y, term.cursor.x + numChars);
winModifyRange(term.cursor.y, term.cursor.x,
term.cursor.y, term.cursor.x + numChars);
}
/* Set various terminal attributes
*/
static void emulParamInterpret(void)
{
int idx;
if (term.numParams == 0) term.params[term.numParams++] = 0;
for (idx = 0; idx < term.numParams; ++idx) {
switch (term.params[idx]) {
case 0: clearAttribs(); break;
case 1: setBold(); break;
case 4: DEBUG("underline ON\n"); break;
case 5: DEBUG("blink ON\n"); break;
case 7: setInverse(TRUE); break;
case 8: DEBUG("concealed\n"); break;
case 10: emulCharSet(0); break;
case 11: emulCharSet(1); break;
case 22: DEBUG("alt intensity OFF\n"); break;
case 24: DEBUG("underline OFF\n"); break;
case 25: DEBUG("blink OFF\n"); break;
case 27: setInverse(FALSE); break;
case 30: setForeground(Black); break;
case 31: setForeground(Red); break;
case 32: setForeground(Green); break;
case 33: setForeground(Yellow); break;
case 34: setForeground(Blue); break;
case 35: setForeground(Magenta); break;
case 36: setForeground(Cyan); break;
case 37: setForeground(White); break;
case 39:
DEBUG("underline OFF\n");
setForeground(FG(term.blankAttr));
break;
case 40: setBackground(Black); break;
case 41: setBackground(Red); break;
case 42: setBackground(Green); break;
case 43: setBackground(Yellow); break;
case 44: setBackground(Blue); break;
case 45: setBackground(Magenta); break;
case 46: setBackground(Cyan); break;
case 47: setBackground(White); break;
case 49: setBackground(BG(term.blankAttr)); break;
}
}
}
/* Report cursor address
*/
static void emulCursorReport(void)
{
char buff[32];
if (term.numParams == 0)
term.params[term.numParams++] = 0;
switch (term.params[0]) {
case 5:
emulFuncKeyPress("\x1b[0n");
break;
case 6:
if (term.cursorRelative && term.haveRegion)
sprintf(buff, "\x1b[%d;%dR",
term.cursor.y - term.scrollTop + 1, term.cursor.x + 1);
else
sprintf(buff, "\x1b[%d;%dR", term.cursor.y + 1, term.cursor.x + 1);
emulFuncKeyPress(buff);
break;
}
}
/* Report terminal status
*/
static void emulStatusReport(void)
{
if (term.numParams == 0)
term.params[term.numParams++] = 0;
if (term.params[0] == 0)
emulFuncKeyPress("\x1b[?1;0c");
}
/* Set various terminal modes
*/
static void emulSetMode(BOOL set)
{
if (term.numParams != 1)
return;
if (term.seenQuestion) {
switch (term.params[0]) {
case 1:
term.ansiCursorKeys = set;
break;
case 5:
/* Switch to/from inverse video
*/
if (term.inverseVideo == set)
break;
linesInvertAll();
winModifyRange(0, 0, term.winSize.cy, term.winSize.cx);
setInverse(set);
break;
case 6:
term.cursorRelative = set;
break;
case 7:
term.lineWrap = set;
break;
case 8:
term.autoRepeat = set;
break;
case 25:
termSetCursorMode(set);
break;
case 9:
/* X10 compatible mouse reporting, maybe later */
break;
case 1000:
/* X11 compatible mouse reporting */
if (emulGetTerm()->flags & ETF_MOUSE_EVENT)
{
term.mouseReporting = set;
}
break;
case 1001:
/* X11 compatible mouse tracking, not yet implemented */
break;
#if 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -