📄 vt.c
字号:
/*
* KON2 - Kanji ON Console -
* Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp)
*
* CCE - Console Chinese Environment -
* Copyright (C) 1998-1999 Rui He (herui@cs.duke.edu)
*
* VCOnGUI - Virtual Console On MiniGUI -
* Copyright (C) 1999 Wei Yongming (ymwei@263.net)
*/
/*
** This source is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This software is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the Free
** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA
*/
// Create date: 1999.09.23
//
// Modify records:
//
// Who When Where For What Status
//-----------------------------------------------------------------------------
//
// TODO:
//
/* Console driver handling, may have a look at CCE 0.11's console.c
and Linux kernel source code: /usr/src/linux/drivers/char/console.c
The below code doesn't handle all of the ANSI required ESC stuff
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/vt.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <signal.h>
#include <termio.h>
#include <pthread.h>
#include <semaphore.h>
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/control.h>
#include "vcongui.h"
#include "defs.h"
#include "vc.h"
#include "child.h"
#include "terminal.h"
#include "vt.h"
#define CHAR_NUL '\x00'
#define CHAR_BEL '\x07'
#define CHAR_BS '\x08'
#define CHAR_HT '\x09'
#define CHAR_LF '\x0A'
#define CHAR_VT '\x0B'
#define CHAR_FF '\x0C'
#define CHAR_CR '\x0D'
#define CHAR_SO '\x0E'
#define CHAR_SI '\x0F'
#define CHAR_XON '\x11'
#define CHAR_XOFF '\x12'
#define CHAR_CAN '\x18'
#define CHAR_SUB '\x1A'
#define CHAR_ESC '\x1B'
#define CHAR_DEL '\x7F'
#define CHAR_CSI '\x9B'
#define CHAR_SS2 '\x8E'
#define LEN_REPORT 9
/* Call the routines in vc.c
TextInsertChar/TextDeleteChar
ScrollUp/ScrollDown
TextSput/TextWput
TextMoveUp/TextMoveDown
TextClearAll/TextClearEol/TextClearEos
*/
/****************************************************************************
* SaveAttr/RestoreAttr *
****************************************************************************/
static void SaveAttr(CONINFO *con)
{
struct attrStack *tmp;
tmp = (struct attrStack *)malloc(sizeof(struct attrStack));
if (con->saveAttr)
tmp->prev = con->saveAttr;
else
tmp->prev = NULL;
con->saveAttr = tmp;
con->saveAttr->x = con->x;
con->saveAttr->y = con->y;
con->saveAttr->attr = con->attr;
con->saveAttr->fcol = con->fcol;
con->saveAttr->bcol = con->bcol;
}
static void RestoreAttr(CONINFO *con)
{
struct attrStack *tmp;
if (con->saveAttr) {
con->x = con->saveAttr->x;
con->y = con->saveAttr->y;
con->attr = con->saveAttr->attr;
con->fcol = con->saveAttr->fcol;
con->bcol = con->saveAttr->bcol;
tmp = con->saveAttr;
con->saveAttr = tmp->prev;
free(tmp);
}
}
/**************************************************************************
* EscSetAttr *
**************************************************************************/
static void EscSetAttr (CONINFO *con, int col)
{
static const u_char table[] = {0, 4, 2, 6, 1, 5, 3, 7};
u_char swp;
switch(col) {
case 0: /* off all attributes */
con->bcol = 0;
con->fcol = 7;
con->attr = 0;
break;
case 1: // highlight, fcolor
con->attr |= ATTR_HIGH;
con->fcol |= 8;
break;
case 21: // clear highlight
con->attr &= ~ATTR_HIGH;
con->fcol &= ~8;
break;
case 4: // underline, bcolor
con->attr |= ATTR_ULINE;
con->bcol |= 8;
break;
case 24: // clear underline
con->attr &= ~ATTR_ULINE;
con->bcol &= ~8;
break;
case 7: // reverse
if (!(con->attr & ATTR_REVERSE)) {
con->attr |= ATTR_REVERSE;
swp = con->fcol & 7;
if (con->attr & ATTR_ULINE)
swp |= 8;
con->fcol = con->bcol & 7;
if ((con->attr & ATTR_HIGH) && con->fcol)
con->fcol |= 8;
con->bcol = swp;
}
break;
case 27: // clear reverse
if (con->attr & ATTR_REVERSE) {
con->attr &= ~ATTR_REVERSE;
swp = con->fcol & 7;
if (con->attr & ATTR_ULINE)
swp |= 8;
con->fcol = con->bcol & 7;
if ((con->attr & ATTR_HIGH) && con->fcol)
con->fcol |= 8;
con->bcol = swp;
}
break;
default:
if (col >= 30 && col <= 37) // assign foreground color
{
swp = table[col - 30];
if (con->attr & ATTR_REVERSE) {
if (con->attr & ATTR_ULINE)
swp |= 8;
con->bcol = swp;
}
else {
if (con->attr & ATTR_HIGH)
swp |= 8;
con->fcol = swp;
}
}
else if (col >= 40 && col <= 47) // assign background color
{
swp = table[col - 40];
if (con->attr & ATTR_REVERSE) {
if (con->attr & ATTR_HIGH)
swp |= 8;
con->fcol = swp;
}
else {
if (con->attr & ATTR_ULINE)
swp |= 8;
con->bcol = swp;
}
}
break;
}
}
static void VtSetMode (CONINFO *con, u_char mode, bool sw)
{
switch(mode) {
case 4:
con->ins = sw;
break;
case 25:
con->cursorsw = sw;
break;
}
}
static void EscReport (CONINFO *con, u_char mode, u_short arg)
{
char report[LEN_REPORT];
switch(mode) {
case 'n':
if (arg == 6) {
int x = (con->x < con->xmax) ? con->x : con->xmax;
int y = (con->y < con->ymax) ? con->y : con->ymax;
sprintf(report, "\x1B[%d;%dR", y + 1, x + 1);
}
else if (arg == 5)
strcpy(report, "\x1B[0n\0");
break;
case 'c':
if (arg == 0)
strcpy(report, "\x1B[?6c\0");
break;
}
write (con->masterPty, report, strlen (report));
}
/* ESC [ ..... */
static void EscBracket (CONINFO *con, u_char ch)
{
u_char n;
if (ch >= '0' && ch <= '9') {
con->varg[con->narg] = (con->varg[con->narg] * 10) + (ch - '0');
}
else if (ch == ';') {
if (con->narg < MAX_NARG)
con->narg ++;
else
con->esc = NULL;
}
else {
con->esc = NULL;
switch (ch)
{
case 'K':
TextClearEol (con, con->varg[0]);
break;
case 'J':
TextClearEos (con, con->varg[0]);
break;
// ESC[%dX - I can't find it in /etc/termcap, but dialog-based
// program used it. - holly
case 'X':
TextClearChars (con, con->varg[0]);
break;
case 'A':
con->y -= con->varg[0] ? con->varg[0]: 1;
if (con->y < con->ymin) {
con->scroll -= con->y - con->ymin;
con->y = con->ymin;
}
break;
case 'B':
con->y += con->varg[0] ? con->varg[0]: 1;
if (con->y > con->ymax) {
con->scroll += con->y - con->ymin;
con->y = con->ymax;
}
break;
case 'C':
con->x += con->varg[0] ? con->varg[0]: 1;
con->wrap = false;
break;
case 'D':
con->x -= con->varg[0] ? con->varg[0]: 1;
con->wrap = false;
break;
case 'G':
con->x = con->varg[0] ? con->varg[0] - 1: 0;
con->wrap = false;
break;
case 'P':
TextDeleteChar (con, con->varg[0] ? con->varg[0]: 1);
break;
case '@':
TextInsertChar (con, con->varg[0] ? con->varg[0]: 1);
break;
case 'L':
TextMoveDown (con, con->y, con->ymax, con->varg[0]?con->varg[0]:1);
break;
case 'M':
TextMoveUp (con, con->y, con->ymax, con->varg[0]?con->varg[0]:1);
break;
case 'H':
case 'f':
if (con->varg[1])
con->x = con->varg[1] - 1;
else
con->x = 0;
con->wrap = false;
case 'd':
con->y = con->varg[0] ? con->varg[0] - 1: 0;
break;
case 'm':
for (n = 0; n <= con->narg; n ++)
EscSetAttr (con, con->varg[n]);
break;
case 'r':
con->ymin = con->varg[0]? (con->varg[0] - 1): 0;
con->ymax = con->varg[1]? (con->varg[1] - 1): (con->dispymax - 1);
con->x = 0;
con->y = con->ymin;
con->wrap = false;
#if 1
if (con->ymin || (con->ymax != con->dispymax - 1))
con->soft = true;
else
con->soft = false;
#endif
break;
case 'l':
for (n = 0; n <= con->narg; n ++)
VtSetMode (con, con->varg[n], false);
break;
case 'h':
for (n = 0; n <= con->narg; n ++)
VtSetMode (con, con->varg[n], true);
break;
case '?':
con->question = true;
con->esc = EscBracket;
break;
case 's':
SaveAttr (con);
break;
case 'u':
RestoreAttr (con);
break;
case 'n':
case 'c':
if (con->question != true)
EscReport (con, ch, con->varg[0]);
break;
case 'R':
break;
}
if (con->esc == NULL) {
con->question = false;
con->narg = 0;
for ( n = 0; n < MAX_NARG; n++ )
con->varg[n] = 0;
}
}
}
CODINGINFO SCodingInfo [] = {
/* latin1(French, Spanish, ...) */
{"ISO8859-1", 'B', 'A'},
/* latin2 */
{"ISO8859-2", 'B', 'B'},
/* latin3 */
{"ISO8859-3", 'B', 'C'},
/* latin4 */
{"ISO8859-4", 'B', 'D'},
/* Russian */
{"ISO8859-5", 'B', 'L'},
/* Arabic */
{"ISO8859-6", 'B', 'G'},
/* Greek */
{"ISO8859-7", 'B', 'F'},
/* Hebrew */
{"ISO8859-8", 'B', 'H'},
/* latin5 */
{"ISO8859-9", 'B', 'M'},
/* Japanese */
{"JISX0201.1976-0", 'J', 'I'},
/* DUMB */
{NULL, 0, 0}
};
CODINGINFO DCodingInfo [] = {
/* DF_GB2312 */
{"GB2312.1980-0", 'A', 0},
/* DF_JISX0208 */
{"JISX0208.1983-0", 'B', 0},
/* DF_KSC5601 */
{ "KSC5601.1987-0", 'C', 0},
/* DF_JISX0212 */
{"JISX0212", 'D', 0, },
/* DF_BIG5_0 */
{"BIG5.HKU-0", '0', 0},
/* DF_BIG5_1 */
{"BIG5.HKU-0", '1', 0},
/* DUMB */
{NULL, 0, 0}
};
static void EscSetDCodeG0 (CONINFO *con, u_char ch)
{
int i = 0;
switch(ch) {
case '(': /* EscSetDCodeG0 */
case ')': /* EscSetDCodeG1 */
return;
case '@':
ch = 'B';
default:
while (DCodingInfo [i].sign0) {
if (DCodingInfo[i].sign0 == ch) {
con->db = (u_char)i|LATCH_1;
break;
}
i ++;
}
con->trans = CS_DBCS;
break;
}
con->esc = NULL;
}
static void EscSetSCodeG0 (CONINFO *con, u_char ch)
{
int i = 0;
switch(ch) {
case 'U':
con->g[0] = CS_GRAPH;
break;
default:
while (SCodingInfo [i].sign0) {
if (SCodingInfo [i].sign0 == ch) {
con->sb = (u_char)i;
con->g[0] = CS_LEFT;
break;
}
else if (SCodingInfo [i].sign1 == ch) {
con->sb = (u_char)i;
con->g[0] = CS_RIGHT;
break;
}
i ++;
}
}
con->trans = con->g[0];
con->esc = NULL;
}
static void EscSetSCodeG1 (CONINFO *con, u_char ch)
{
switch(ch) {
case 'U':
con->g[1] = CS_LEFT;
break;
case '0':
con->g[1] = CS_GRAPH;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -