📄 nxterm.c
字号:
/* * Copyright (c) 2003 Century Software, Inc. All Rights Reserved. * * This file is part of the PIXIL Operating Environment * * The use, copying and distribution of this file is governed by one * of two licenses, the PIXIL Commercial License, or the GNU General * Public License, version 2. * * Licensees holding a valid PIXIL Commercial License may use this file * in accordance with the PIXIL Commercial License Agreement provided * with the Software. Others are governed under the terms of the GNU * General Public License version 2. * * This file may be distributed and/or modified under the terms of the * GNU General Public License version 2 as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included * in the packaging of this file. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. * * RESTRICTED RIGHTS LEGEND * * Use, duplication, or disclosure by the government is subject to * restriction as set forth in paragraph (b)(3)(b) of the Rights in * Technical Data and Computer Software clause in DAR 7-104.9(a). * * See http://www.pixil.org/gpl/ for GPL licensing * information. * * See http://www.pixil.org/license.html or * email cetsales@centurysoftware.com for information about the PIXIL * Commercial License Agreement, or if any conditions of this licensing * are not clear to you. */ /* * Portions Copyright (C) 1994,95,96 by Torsten Scherer (TeSche) */#include <stdio.h>#include <signal.h>#include <sys/time.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>#include <pwd.h>#include <string.h>#include <sys/ioctl.h>#include <termios.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <fcntl.h>#ifdef __FreeBSD__#include <libutil.h>#endif#define MWINCLUDECOLORS#include "nano-X.h"#include "nxterm.h"#define DEF_TITLE "Linux Terminal"#define DEF_STYLE (GR_WM_PROPS_APPWINDOW)#define DEF_COLOR GR_COLOR_WINDOWTEXT#define DEF_GEOMETRY "80x25+0-0"#ifdef linux#define NSIG _NSIG#endif#define SMALLBUFFER 80GR_WINDOW_ID w1; /* id for window */GR_GC_ID gc1; /* text gc */GR_GC_ID gc2; /* fillrect gc */GR_FONT_ID regFont;GR_BOOL havefocus = GR_FALSE;int pid, console;int pipeh;int wChar; /* width/height of character */int hChar;int wScreen; /* width/height of terminal window */int hScreen;int col, row;char *begscr = NULL;char **vscreen;int inresize = 0;int escstate, curx, cury, curon, curvis, reverse;int savx, savy, wrap;int sbufcnt = 0;int sbufx, sbufy;char sbuf[SMALLBUFFER + 1];int g_colors[] = { BLACK, RED, GREEN, BROWN, BLUE, MAGENTA, CYAN, GRAY, LTGRAY, LTRED, LTGREEN, YELLOW, LTBLUE, LTMAGENTA, LTCYAN, WHITE};int g_fgcolor = 0;int g_bgcolor = 15;#define TEXT_BOLD 0x01int g_attr = 0;int term_init();void hide_cursor(void);void vscroll(void);voidredisplay(void){ int y; hide_cursor(); for (y = 0; y < row; ++y) GrText(w1, gc1, 0, y * hChar, vscreen[y], col, GR_TFTOP);} /* * Resize cols and rows to fit passed window size */voidresize(GR_SIZE width, GR_SIZE height){ int y, x; int newcol, newrow; char *newbegscr; char **newvscreen; char buf[32]; newcol = width / wChar; newrow = height / hChar; newbegscr = malloc(newrow * newcol * sizeof(char)); newvscreen = malloc(newrow * sizeof(char *)); if (!newbegscr || !newvscreen) { fprintf(stderr, "Can't allocate screen\n"); exit(1); } for (y = 0; y < newrow; ++y) newvscreen[y] = &newbegscr[y * newcol]; memset(newbegscr, ' ', newrow * newcol); /* copy old vscreen if present */ if (begscr) { for (y = 0; y < row && y < newrow; ++y) for (x = 0; x < col && x < newcol; ++x) newvscreen[y][x] = vscreen[y][x]; free(vscreen); free(begscr); } /* set new global values */ begscr = newbegscr; vscreen = newvscreen; col = newcol; row = newrow; wScreen = width; hScreen = height; /* set TERMCAP= string */ if (termcap_string) { sprintf(termcap_string + strlen(termcap_string), "li#%d:co#%d:", row, col); putenv(termcap_string); } /* set COLUMN= and LINES= variables */ sprintf(buf, "%d", col); setenv("COLUMNS", buf, 1); sprintf(buf, "%d", row); setenv("LINES", buf, 1); /* JHC - this is not right - we shouldn't restart the shell, but just accept the resize as it happens */#ifdef NOTUSED /* * Start new shell after resetting environment variables... */ if (pipeh) { ++inresize; hide_cursor(); if (++cury >= row) { vscroll(); cury = row - 1; } curx = 0; close(pipeh); pause(); pipeh = term_init(); --inresize; }#endif}voidsflush(void){ if (sbufcnt) { GrText(w1, gc1, sbufx * wChar, sbufy * hChar, sbuf, sbufcnt, GR_TFTOP); sbufcnt = 0; }}voidsadd(int c){ if (sbufcnt == SMALLBUFFER) sflush(); if (!sbufcnt) { sbufx = curx; sbufy = cury; } sbuf[sbufcnt++] = c; vscreen[cury][curx] = c;}voidshow_cursor(void){ GrSetGCMode(gc1, GR_MODE_XOR); GrSetGCForeground(gc1, WHITE); GrFillRect(w1, gc1, curx * wChar, cury * hChar + 1, wChar, hChar - 1); GrSetGCForeground(gc1, g_colors[g_fgcolor]); GrSetGCMode(gc1, GR_MODE_SET);}voiddraw_cursor(void){ if (!curvis) { curvis = 1; show_cursor(); }}voidhide_cursor(void){ if (curvis) { curvis = 0; show_cursor(); }}voidvscroll(void){ int y; char *p; hide_cursor(); GrCopyArea(w1, gc1, 0, 0, col * wChar, (row - 1) * hChar, w1, 0, hChar, MWROP_SRCCOPY); p = vscreen[0]; for (y = 0; y < row - 1; ++y) vscreen[y] = vscreen[y + 1]; vscreen[row - 1] = p; memset(vscreen[row - 1], ' ', col); GrFillRect(w1, gc2, 0, (row - 1) * hChar, col * wChar, hChar);}struct{ unsigned long key; char *keycode;}g_keys[] ={ { MWKEY_UP, "\033[A"} , { MWKEY_DOWN, "\033[B"} , { MWKEY_RIGHT, "\033[C"} , { MWKEY_LEFT, "\033[D"} , { 0, ""}};/* generate keystrokes for the VT100 *//* FIXME: Make this table driven */voidhandle_key(int key){ int i; for (i = 0; g_keys[i].key; i++) if (g_keys[i].key == key) { write(pipeh, g_keys[i].keycode, strlen(g_keys[i].keycode)); return; }}voidhandle_attribute(int attr){ switch (attr) { case 0: g_fgcolor = 0; g_bgcolor = 15; g_attr = 0; break; case 1: if (g_fgcolor < 8) g_fgcolor += 8; g_attr |= TEXT_BOLD; break; case 39: g_fgcolor = 0; break; case 49: g_bgcolor = 15; break; case 30 ... 37: g_fgcolor = attr - 30; if (g_attr & TEXT_BOLD) g_fgcolor += 8; break; case 40 ... 47: g_bgcolor = attr - 40; break; default: printf("We don't handle attribute %d yet\n", attr); return; } GrSetGCForeground(gc1, g_colors[g_fgcolor]); GrSetGCBackground(gc1, g_colors[g_bgcolor]);}/* A handler for the CSI (Code Sequence Introducer) sequences */voidhandle_csi(int c){ /* We can handle up to two integer arguments on the sequence */ static int args[2] = { 0, 0 }; static int argc = 0; int arg = 0; switch (c) { case 'm': for (arg = 0; arg <= argc; arg++) handle_attribute(args[arg]); break; case ';': argc++; return; default: if (c >= '0' && c <= '9') args[argc] = (args[argc] * 10) + (c - '0'); else printf("Warning - unknown char '%c' in the sequence\n", c); return; } args[0] = args[1] = 0; escstate = 0; argc = 0;}voidesc5(int c){ /* setting background color */ //bgcolor = colors[c]; GrSetGCBackground(gc1, g_colors[g_bgcolor]); GrSetGCForeground(gc2, g_colors[g_bgcolor]); escstate = 0;}voidesc4(int c){ /* setting foreground color */ //fgcolor = colors[c]; GrSetGCForeground(gc1, g_colors[g_fgcolor]); escstate = 0;}voidesc3(int c){ /* cursor position x axis */ curx = (c - 32) & 0xff; if (curx >= col) curx = col - 1; else if (curx < 0) curx = 0; escstate = 0;}voidesc2(int c){ /* cursor position y axis */ cury = (c - 32) & 0xff; if (cury >= row) cury = row - 1; else if (cury < 0) cury = 0; escstate = 3;}voidesc1(int c){ /* various control codes */ int y, x; escstate = 0; switch (c) { case 'A': /* cursor up */ if (--cury < 0) cury = 0; break; case 'B': /* cursor down */ if (++cury >= row) cury = row - 1; break; case 'C': /* cursor right */ if (++curx >= col) curx = col - 1; break; case 'D': /* cursor left */ if (--curx < 0) curx = 0; break; case 'E': /* clear screen & home */ memset(begscr, ' ', row * col); GrClearWindow(w1, 0); curx = 0; cury = 0; break; case 'H': /* cursor home */ curx = 0; cury = 0; break; case 'I': /* reverse index */ if (--cury < 0) cury = 0; break; case 'J': /* erase to end of page */ if (cury < row - 1) { for (y = cury; y < row; ++y) memset(vscreen[y], ' ', col); GrFillRect(w1, gc2, 0, (cury + 1) * hChar, wScreen, (row - 1 - cury) * hChar); } for (x = curx; x < col; ++x) vscreen[cury][x] = ' '; GrFillRect(w1, gc2, curx * wChar, cury * hChar, (col - curx) * wChar, hChar); break; case 'K': /* erase to end of line */ for (x = curx; x < col; ++x) vscreen[cury][x] = ' '; GrFillRect(w1, gc2, curx * wChar, cury * hChar, (col - curx) * wChar, hChar); break; case 'L': /* insert line */ if (cury < row - 1) vscroll(); //FIXME buggy curx = 0; break; case 'M': /* delete line */ if (cury < row - 1) vscroll(); curx = 0; break; case 'Y': /* position cursor */ escstate = 2; break; case 'b': /* set foreground color */ escstate = 4; break; case 'c': /* set background color */ escstate = 5; break; case 'd': /* erase beginning of display */ if (cury > 0) { for (y = 0; y < cury; ++y) memset(vscreen[y], ' ', col); GrFillRect(w1, gc2, 0, 0, wScreen, cury * hChar); } if (curx > 0) { for (x = 0; x < curx; ++x) vscreen[cury][x] = ' '; GrFillRect(w1, gc2, 0, cury * hChar, curx * wChar, hChar); } break; case 'e': /* enable cursor */ curon = 1; break; case 'f': /* disable cursor */ curon = 0; break; case 'j': /* save cursor position */ savx = curx; savy = cury; break; case 'k': /* restore cursor position */ curx = savx; cury = savy; break; case 'l': /* erase entire line */ memset(vscreen[cury], ' ', col); GrFillRect(w1, gc2, 0, cury * hChar, wScreen, hChar); curx = 0; break; case 'o': /* erase beginning of line */ if (curx > 0) { for (x = 0; x < curx; ++x) vscreen[cury][x] = ' '; GrFillRect(w1, gc2, 0, cury * hChar, curx * wChar, hChar); } break; case 'p': /* enter reverse video mode */ if (!reverse) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -