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

📄 emul.c

📁 dtelent是开源的开发项目
💻 C
📖 第 1 页 / 共 4 页
字号:
/* emul.c
 * Copyright (c) 1997 David Cole
 *
 * Terminal emulation
 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include "utils.h"
#include "term.h"
#include "termwin.h"
#include "lines.h"
#include "emul.h"
#include "connect.h"
#include "dtelnet.h"
#include "raw.h"
#include "socket.h"
#include "log.h"
#include "status.h"
#include "printing.h"
#include "editor.h"
#include "dtchars.h"

#define DEBUG(str)

static unsigned char usCharSet[256] = {
      0,   1,   2,   3,   4,   5,   6,   7,
      8,   9,  10,  11,  12,  13,  14,  15,
     16,  17,  18,  19,  20,  21,  22,  23,
     24,  15,  26,  27,  28,  29,  30,  31,
    ' ', '!', '"', '#', '$', '%', '&', '\'',
    '(', ')', '*', '+', ',', '-', '.', '/',
    '0', '1', '2', '3', '4', '5', '6', '7',
    '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
    '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
    'x', 'y', 'z', '{', '|', '}', '~', 127,
    128, 129, 130, 131, 132, 133, 134, 135,
    136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151,
    152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167,
    168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183,
    184, 185, 186, 187, 188, 189, 190, 191,
    192, 193, 194, 195, 196, 197, 198, 199,
    200, 201, 202, 203, 204, 205, 206, 207,
    208, 209, 210, 211, 212, 213, 214, 215,
    216, 217, 218, 219, 220, 221, 222, 223,
    224, 225, 226, 227, 228, 229, 230, 231,
    232, 233, 234, 235, 236, 237, 238, 239,
    240, 241, 242, 243, 244, 245, 246, 247,
    248, 249, 250, 251, 252, 253, 254, 255
};
static unsigned char graphicsCharSet[256] = {
      0,   1,   2,   3,   4,   5,   6,   7,
      8,   9,  10,  11,  12,  13,  14,  15,
     16,  17,  18,  19,  20,  21,  22,  23,
     24,  15,  26,  27,  28,  29,  30,  31,
    ' ', '!', '"', '#', '$', '%', '&', '\'',
    '(', ')', '*', '+', ',', '-', '.', '/',
    219, '1', '2', '3', '4', '5', '6', '7',
    '8', '9', ':', ';', '<', '=', '>', '?',
    '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
    'X', 'Y', 'Z', '[', '\\', ']', '^', ' ',
    '`', 177, 254, 254, 254, 254, 248, 241,
    176, 254, 217, 191, 218, 192, 197, 254,
    254, 196, 254, '_', 195, 180, 193, 194,
    179, 243, 242, 227, 254, 156, 250, 127,
    128, 129, 130, 131, 132, 133, 134, 135,
    136, 137, 138, 139, 140, 141, 142, 143,
    144, 145, 146, 147, 148, 149, 150, 151,
    152, 153, 154, 155, 156, 157, 158, 159,
    160, 161, 162, 163, 164, 165, 166, 167,
    168, 169, 170, 171, 172, 173, 174, 175,
    176, 177, 178, 179, 180, 181, 182, 183,
    184, 185, 186, 187, 188, 189, 190, 191,
    192, 193, 194, 195, 196, 197, 198, 199,
    200, 201, 202, 203, 204, 205, 206, 207,
    208, 209, 210, 211, 212, 213, 214, 215,
    216, 217, 218, 219, 220, 221, 222, 223,
    224, 225, 226, 227, 228, 229, 230, 231,
    232, 233, 234, 235, 236, 237, 238, 239,
    240, 241, 242, 243, 244, 245, 246, 247,
    248, 249, 250, 251, 252, 253, 254, 255
};
static unsigned char* ukCharSet = usCharSet;
static unsigned char* altCharSet = usCharSet;
static unsigned char* altGraphicsCharSet = graphicsCharSet;

/* map graphic characters from vt100 code to OEM charset
 * warning: some codes are below 0x20 (eg 0x11 as LARROW)
 */
static unsigned char graphToOEM [] = {
'l', 0xda, 'm', 0xc0, 'k', 0xbf, 'j', 0xd9, 't', 0xc3, 'u', 0xb4,
'v', 0xc1, 'w', 0xc2, 'q', 0xc4, 'x', 0xb3, 'n', 0xc5, 'o', 0x7e,
's', 0x5f, '`', 0x04, 'a', 0xb1, 'f', 0xf8, 'g', 0xf1, '~', 0xfe,
',', 0x11, '+', 0x10, '.', 0x19, '-', 0x18, 'h', 0xb0, 'i', 0xce,
'0', 0xdb, 'p', 0xc4, 'r', 0xc4, 'y', 0xf3, 'z', 0xf2, '{', 0xe3,
'|', 0xd8, '}', 0x7d, 0
};
/*
 * terminating zero does not count into length
*/
#define NgraphToOEM ((sizeof (graphToOEM) -1)/2)

static char title[sizeof(term.title)];
static int titleLen;

static Emul currEmul = { "" /* empty terminal name */ };

static void emulCharSet(int charSet);
static void emulCharDeleteCore (int numChars, BOOL bKeyboard);

/* Return pointer to the description of the terminal currently being
 * emulated.
 */
Emul* emulGetTerm()
{
    return &currEmul;
}

/* Set the terminal type to emulate by name
 *
 * Args:
 * name - the name of the terminal type to emulate
 */
void emulSetTerm(const char* name)
{
    telnetGetTermProfile(&currEmul, name);
}

/* Set the from/to server charsets specified by name */
void emulSetCharset(const char *name)
{
    dtcEC_Load (name, currEmul.ctServerToOem, currEmul.ctOemToServer,
		currEmul.ctAnsiToServer, currEmul.ctServerToAnsi);
    currEmul.fAnsi = strcmp (name, "OEM")!=0;
}

/**************************
 * ATTRIBUTE MANIPULATION *
 **************************/

/* Set the foreground attribute for new characters
 *
 * Args:
 * color - ANSI color number 0 .. 7
 */
static void setForeground(int color)
{
    term.currAttr &= ~FG_MASK;
    term.currAttr |= (unsigned char)FG(color);
}

/* Set the background attribute for new characters
 *
 * Args:
 * color - ANSI color number 0 .. 7
 */
static void setBackground(int color)
{
		term.currAttr &= ~BG_MASK;
		term.currAttr |= (unsigned char)BG(color);
}

/* Make the current foreground attribute bold
 */
static void setBold(void)
{
    term.currAttr |= BOLD;
}

/* Set or clear the inverse attribute
 *
 * Args:
 * inverse - when TRUE, foreground and background are transposed.
 */
static void setInverse(BOOL inverse)
{
    term.inverseVideo = inverse;
}

/* Restore the default color attributes
 */
static void clearAttribs(void)
{
    term.currAttr = term.blankAttr;
    term.inverseVideo = FALSE;
}

/* Return current character attributes
 */
unsigned char getCurrAttr()
{
    if (!term.inverseVideo)
	return term.currAttr;
    return (unsigned char)REVERSE(term.currAttr);
}

/**********************
 * TERMINAL EMULATION *
 **********************/

/* Clear parameters used for various terminal commands
 */
static void emulParamInit(void)
{
    titleLen = 0;
    term.numParams = 0;
    term.numSParam = 0;    /* no byte collected yet */
    term.stateSParam = 0;  /* waiting for simple bytes */
    memset(term.params, 0, sizeof(term.params));
    term.seenQuestion = FALSE;
}

/* Start building the next command parameter
 */
static void emulParamNext(void)
{
    if (term.numParams < sizeof(term.params) / sizeof(term.params[0]))
	term.numParams++;
}

/* Accumulate a digit in the current command parameter
 *
 * Args:
 * num - a decimal digit 0 .. 9
 */
static void emulParamAdd(int num)
{
    if (term.numParams == 0)
	term.numParams++;
    term.params[term.numParams - 1]
	= term.params[term.numParams - 1] * 10 + num;
}

static void emulSParamAdd (char byte)
{
    int val;

    if (term.numSParam >= MAXSPARAM) return; /* ignore */
    else if (term.stateSParam == 0) {
	term.sparam [term.numSParam++] = byte;
    } else {
	val = fromhex (byte);
	if (term.stateSParam == 1) {
	    term.sparam [term.numSParam] = (char)(val<<4);
	    term.stateSParam = 2;
	} else {
	    term.sparam [term.numSParam] += (char)val;
	    ++term.numSParam;
	    term.stateSParam = 1;
	}
    }
}

/* Capture new window title from the terminal input
 */
static void emulAddTitle(char c)
{
    if (titleLen < sizeof(title) - 1) {
	title[titleLen++] = c;
	title[titleLen] = '\0';
    }
}

/* Set the window title from the captured text
 */
static void emulSetTitle(void)
{
    if (term.numParams == 0)
	term.params[term.numParams++] = 0;
    switch (term.params[0]) {
    case 0:
    case 2:
	termSetTitle(title);
	break;
    }
    titleLen = 0;
}

/* Check to see if the cursor has been moved off the terminal.  If it
 * has, scroll the terminal to bring the cursor back.
 */
static void emulCursorCheck(void)
{
    if (term.haveRegion) {
	/* Scrolling a region has different semantics - we do not
	 * update the history if we have a region set.
	 */
	if (term.cursor.y == term.scrollBottom) {
	    /* We have moved the cursor off the bottom of the region -
	     * scroll the region.
	     */
	    term.cursor.y--;
	    if (term.topVisibleLine + term.scrollBottom > winTerminalTopLine())
		winScrollRegion(1);
	    linesDelete(term.scrollTop, term.scrollBottom, 1);
	} else if (term.cursor.y == term.scrollTop - 1) {
	    term.cursor.y++;
	    if (term.topVisibleLine + term.scrollBottom > winTerminalTopLine())
		winScrollRegion(-1);
	    linesInsert(term.scrollTop, term.scrollBottom, 1);
	}
    } else {
	if (term.cursor.y == term.winSize.cy) {
	    /* We have moved the cursor off the bottom of the terminal -
	     * scroll the window if we have not scrolled back in the
	     * history buffer.
	     */
	    term.cursor.y--;
	    if (term.topVisibleLine == winTerminalTopLine()) {
		winScrollRegion(1);
		term.topVisibleLine++;
	    }
	    linesNewLine();
	} else if (term.cursor.y == -1) {
	    term.cursor.y++;
	    if (term.topVisibleLine + term.winSize.cy > winTerminalTopLine())
		winScrollRegion(-1);
	    linesInsert(0, term.winSize.cy, 1);
	}
    }

    /* Make sure we create lines to the cursor position.
     */
    linesCreateTo(term.cursor.y);
}

/* If a character added to the end of the current line will cause a
 * line wrap, perform necessary actions.
 */
static void emulCheckWrap(void)
{
    if (term.cursor.x == term.winSize.cx) {
	if (term.lineWrap) {
	    /* Wrap to start of next line
	     */
	    int lineIdx = linesTerminalToLine(term.cursor.y);
	    Line* line;
	    linesCreateTo(lineIdx);
	    line = linesGetLine(lineIdx);
	    /* Remember that we wrapped this line.  This allows us to
	     * copy/paste lines that wrap without getting spurious end
	     * of line sequences.
	     */
	    if (line != NULL)
		term.lineList[lineIdx]->wrapped = 1;
	    term.cursor.x = 0;
	    term.cursor.y++;
	} else
	    /* Overwrite the character at the end of the line
	     */
	    term.cursor.x--;
    }

    /* Line wrap might cause the terminal to scroll
     */
    emulCursorCheck();
}

/* Carriage Return moves cursor to the beginning of the current line
 */
static void emulCarriageReturn(void)
{
    term.cursor.x = 0;
    emulCursorCheck();
}

/* Line Feed moves cursor down one line.
 */
static void emulLineFeed(void)
{
    if (rawInBinaryMode())
	emulCarriageReturn();
    term.cursor.y++;
    emulCursorCheck();
}

/* Move cursor to the next tab stop.  The cursor always stays on the
 * current line.
 */
static void emulTab(void)
{
    if (printingIsActive()){
        printingAddChar('\t');
        return;
    }

    /* Move the cursor */
    do
	term.cursor.x++;
        while (term.cursor.x < MaxLineLen
	   && !term.tabStops[term.cursor.x]);

    /* Make sure that we do not move the cursor off the end of the
     * visible line.
     */
    if (term.cursor.x > term.winSize.cx)
	term.cursor.x = term.winSize.cx;
}

/* Move cursor to the previous tab stop.
 */
static void emulBacktab(void)
{
    do
	term.cursor.x--;
    while (term.cursor.x > 0 && !term.tabStops[term.cursor.x]);

    if (term.cursor.x < 0)
	term.cursor.x = 0;
}

/* Tab forward <param-0> tab stops.
 */
static void emulTabForward(void)
{
    if (term.numParams != 1)
	return;

    while (term.params[0]-- > 0)
	emulTab();
}

/* Tab backwards <param-0> tab stops.
 */
static void emulTabBackward(void)
{
    if (term.numParams != 1)
	return;

    while (term.params[0]-- > 0)
	emulBacktab();
}

/* Set a tab stop at the current cursor column.
 */
static void emulTabSet(void)
{
    if (term.cursor.x < MaxLineLen)
	term.tabStops[term.cursor.x] = 1;
}

/* Clear tab stops depending on <param-0>;
 *   if 0, clear tab stop at current cursor column
 *   if 3, clear all tab stops
 */
static void emulTabClear(void)
{
    if (term.numParams != 1)
	return;
    switch (term.params[0]) {
    case 0:
	/* Clear tab stop at current cursor column
	 */
	if (term.cursor.x >= 0 && term.cursor.x < MaxLineLen)
	    term.tabStops[term.cursor.x] = 0;
	break;
    case 3:
	/* Clear all tab stops
	 */
	memset(term.tabStops, 0, sizeof(term.tabStops));
	break;
    }
}

/* Reset all tab stops to 8 character interval
 */
static void emulTabReset(void)
{
    int x;

    for (x = 0; x < sizeof(term.tabStops); x++)
	term.tabStops[x] = (char)(x > 0 && (x % 8) == 0);
}

/* Backspace the cursor
 */
static void emulBackspace(BOOL bKeyboard)
{
    int lineIdx;
    Line *line;

    if (term.cursor.x > 0) {
	term.cursor.x--;
        if (bKeyboard)
	    emulCharDeleteCore (1, bKeyboard);
    } else {
	lineIdx = linesTerminalToLine(term.cursor.y);
	if (lineIdx==0) return;
	--lineIdx;

	linesCreateTo(lineIdx);
	line = linesGetLine(lineIdx);
	if (! line->wrapped) return;

/*	term.cursor.x = term.winSize.cx - 1; */

⌨️ 快捷键说明

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