📄 nxterm.c
字号:
/* * nxterm - terminal emulator for Nano-X * * (C) 1994,95,96 by Torsten Scherer (TeSche) * itschere@techfak.uni-bielefeld.de * * - quite some changes for W1R1 * - yet more changes for W1R2 * * TeSche 01/96: * - supports W_ICON & W_CLOSE * - supports /etc/utmp logging for SunOS4 and Linux * - supports catching of console output for SunOS4 * Phx 02-06/96: * - supports NetBSD-Amiga * Eero 11/97: * - unsetenv(DISPLAY), setenv(LINES, COLUMNS). * - Add new text modes (you need to use terminfo...). * Eero 2/98: * - Implemented fg/bgcolor setting. With monochrome server it changes * bgmode variable, which tells in which mode to draw to screen * (M_CLEAR/M_DRAW) and affects F_REVERSE settings. * - Added a couple of checks. * * TODO: * - Allocate and set sensible window palette for fg/bg color setting. * - add scroll-region ('cs') command. Fairly many programs * can take advantage of that. * - Add xterm like mouse event to terminfo key event conversion... :) * - check if current NetBSD really needs ifdefs below with * current W server/library. */#include <stdio.h>#include <signal.h>#include <sys/time.h>#include <utmp.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 <fcntl.h>#define MWINCLUDECOLORS#include "nano-X.h"#include "nxterm.h"#define TITLE "nxterm"#define SMALLBUFFER 80#define LARGEBUFFER 1024/* * some pty helper functions */#ifdef linux#define NSIG _NSIG#endif#ifdef __FreeBSD__#include <libutil.h>#endif/* * some global variables */static GR_WINDOW_ID w1; /* id for window */static GR_GC_ID gc1; /* graphics context */static GR_FONT_ID regFont;/*static GR_FONT_ID boldFont;*/static GR_SCREEN_INFO si; /* screen info */static GR_FONT_INFO fi; /* Font Info */static GR_WINDOW_INFO wi;static GR_GC_INFO gi;static GR_BOOL havefocus = GR_FALSE;static pid_t pid;static short winw, winh, console;static int pipeh;static short cblink = 0, visualbell = 0, debug = 0;#ifdef __FreeBSD__static char pty[SMALLBUFFER];static struct winsize winsz;#endif#define fonh fi.height#define fonw fi.maxwidthint term_init();/****************************************************************************//* * *//* static int isIconified; */static int isMaximized=0;void maximize(void){ static short x0, y0, w, h, w_max,h_max; if (!isMaximized) { w_max=si.cols-wi.bordersize; h_max=si.rows-wi.bordersize; GrMoveWindow(w1,0,0); GrResizeWindow(w1,w_max, h_max); isMaximized=1; } else { GrResizeWindow(w1, w, h); GrMoveWindow(w1, x0, y0); isMaximized=0; }}/****************************************************************************//* * some common tool functions */void sigpipe(int sig){ /* this one musn't close the window *//* _write_utmp(pty, "", "", 0); */ kill(-pid, SIGHUP); _exit(sig);}void sigchld(int sig){/* _write_utmp(pty, "", "", 0); */ _exit(sig);}void sigquit(int sig){ signal(sig, SIG_IGN); kill(-pid, SIGHUP);}/* * this is the wterm terminal code, almost like VT52 */short bgmode, escstate, curx, cury, curon, curvis;short savx, savy, wrap, style;short col, row, colmask = 0x7f, rowmask = 0x7f;/* * something to buffer plain text output */short sbufcnt = 0;short sbufx, sbufy;char lineBuffer[SMALLBUFFER+1];char *sbuf=lineBuffer;void sflush(void){ if (sbufcnt) { GrText(w1,gc1, sbufx*fonw, sbufy*fonh, sbuf, sbufcnt, GR_TFTOP); sbufcnt = 0; }}void lineRedraw(void){ GrSetGCForeground(gc1,gi.background); GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh); GrSetGCForeground(gc1,gi.foreground); if (sbufcnt) { sbuf[sbufcnt] = 0; GrText(w1,gc1, sbufx*fonw, sbufy*fonh, sbuf, sbufcnt, GR_TFTOP); }}void sadd (char c){ if (sbufcnt == SMALLBUFFER) { sflush (); } if (!sbufcnt) { sbufx = curx; sbufy = cury; } sbuf[sbufcnt++] = c;}void show_cursor (void){ GrSetGCMode(gc1,GR_MODE_XOR); GrSetGCForeground(gc1, WHITE); GrFillRect(w1, gc1, curx*fonw, cury*fonh+1, fonw, fonh-1); GrSetGCForeground(gc1, gi.foreground); GrSetGCMode(gc1,GR_MODE_COPY);}void draw_cursor (void){ if (!curvis) { curvis = 1; show_cursor(); }}void hide_cursor (void){ if (curvis) { curvis = 0; show_cursor(); }}void vscroll(int lines){ hide_cursor(); GrCopyArea(w1,gc1,0, 0, winw, winh-(lines*fonh), w1, 0, (lines*fonh), MWROP_SRCCOPY); GrSetGCForeground(gc1,gi.background); GrFillRect(w1, gc1, 0, winh-(lines*fonh), winw, (lines*fonh)); GrSetGCForeground(gc1,gi.foreground); }void esc5(unsigned char c) /* setting background color */{ GrSetGCBackground(gc1, c); GrGetGCInfo(gc1,&gi); escstate = 0;}void esc4(unsigned char c) /* setting foreground color */{ GrSetGCForeground(gc1,c); GrGetGCInfo(gc1,&gi); escstate = 0;}void esc3(unsigned char c) /* cursor position x axis */{ curx = (c - 32) & colmask; if (curx >= col) curx = col - 1; else if (curx < 0) curx = 0; escstate = 0;}void esc2(unsigned char c) /* cursor position y axis */{ cury = (c - 32) & rowmask; if (cury >= row) cury = row - 1; else if (cury < 0) cury = 0; escstate = 3;}void esc1(unsigned char c) /* various control codes */{ static int ReverseMode=0; escstate = 0; switch(c) { case 'A':/* cursor up */ hide_cursor(); if ((cury -= 1) < 0) cury = 0; break; case 'B':/* cursor down */ hide_cursor(); if ((cury += 1) >= row) cury = row - 1; break; case 'C':/* cursor right */ hide_cursor(); if ((curx += 1) >= col) curx = col - 1; break; case 'D':/* cursor left */ hide_cursor(); if ((curx -= 1) < 0) curx = 0; break; case 'E':/* clear screen & home */ GrClearWindow(w1, 0); curx = 0; cury = 0; break; case 'H':/* cursor home */ curx = 0; cury = 0; break; case 'I':/* reverse index */ if ((cury -= 1) < 0) { cury = 0; vscroll(1); } break; case 'J':/* erase to end of page */ if (cury < row-1) { GrSetGCForeground(gc1,gi.background); GrFillRect(w1,gc1, 0,(cury+1)*fonh, winw, (row-1-cury)*fonh); GrSetGCForeground(gc1,gi.foreground); } GrSetGCForeground(gc1,gi.background); GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh); GrSetGCForeground(gc1,gi.foreground); break; case 'K':/* erase to end of line */ GrSetGCForeground(gc1,gi.background); GrFillRect(w1, gc1, curx*fonw, cury*fonh, (col-curx)*fonw, fonh); GrSetGCForeground(gc1,gi.foreground); break; case 'L':/* insert line */ if (cury < row-1) { vscroll(1); } curx = 0; break; case 'M':/* delete line */ if (cury < row-1) { vscroll(1); } 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 *//* w_setmode(win, bgmode); */ if (cury > 0) { GrSetGCForeground(gc1,gi.background); GrFillRect(w1,gc1, 0, 0, winw, cury*fonh); GrSetGCForeground(gc1,gi.foreground); } if (curx > 0) { GrSetGCForeground(gc1,gi.background); GrFillRect(w1,gc1, 0, cury*fonh, curx*fonw, fonh); GrSetGCForeground(gc1,gi.foreground); } 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 */ GrSetGCForeground(gc1,gi.background); GrRect(w1,gc1, 0, cury*fonh, winw, fonh); GrSetGCForeground(gc1,gi.foreground); curx = 0; break; case 'o':/* erase beginning of line */ if (curx > 0) { GrSetGCForeground(gc1,gi.background); GrRect(w1,gc1,0, cury*fonh, curx*fonw, fonh); GrSetGCForeground(gc1,gi.foreground); } break; case 'p':/* enter reverse video mode */ { if(!ReverseMode) { GrSetGCForeground(gc1,gi.background); GrSetGCBackground(gc1,gi.foreground); ReverseMode=1; } } break; case 'q':/* exit reverse video mode */ { if(ReverseMode) { GrSetGCForeground(gc1,gi.foreground); GrSetGCBackground(gc1,gi.background); ReverseMode=0; } } break; case 'v':/* enable wrap at end of line */ wrap = 1; break; case 'w':/* disable wrap at end of line */ wrap = 0; break;/* and these are the extentions not in VT52 */ case 'G': /* clear all attributes */ break; case 'g': /* enter bold mode *//* GrSetGCFont(gc1, boldFont); */ break; case 'h': /* exit bold mode *//* GrSetGCFont(gc1, regFont); */ break; case 'i': /* enter underline mode */ break; /* j, k and l are already used */ case 'm': /* exit underline mode */ break;/* these ones aren't yet on the termcap entries */ case 'n': /* enter italic mode */ break; /* o, p and q are already used */ case 'r': /* exit italic mode */ break; case 's': /* enter light mode */ break; case 't': /* exit ligth mode */ break; default: /* unknown escape sequence */ break; }}/* * un-escaped character print routine */void esc0 (unsigned char c){ switch (c) { case 0: /* * printing \000 on a terminal means "do nothing". * But since we use \000 as string terminator none * of the characters that follow were printed. * * perl -e 'printf("a%ca", 0);' * * said 'a' in a wterm, but should say 'aa'. This * bug screwed up most ncurses programs. * * kay. */ break; case 7: /* bell */ if (visualbell) {/* w_setmode(win, M_INVERS); *//* w_pbox(win, 0, 0, winw, winh); *//* w_test(win, 0, 0); *//* w_pbox(win, 0, 0, winw, winh); */ ; } else { ; GrBell(); } break; case 8: /* backspace */ lineRedraw(); if (--curx < 0) { curx = 0; } break; case 9: /* tab */ { int borg,i; borg=(((curx >> 3) + 1) << 3); if(borg >= col) { borg=col-1; } borg=borg-curx; for(i=0; i < borg; ++i){sadd(' ');} if ((curx = ((curx >> 3) + 1) << 3) >= col) { curx = col - 1; } } break; case 10: /* line feed */ sflush(); if (++cury >= row) { vscroll(1); cury = row-1; } break; case 13: /* carriage return */ sflush(); curx = 0; break; case 27: /* escape */ sflush(); escstate = 1; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -