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

📄 display.c

📁 简介:一个tcp/ip协议实现的完整源代码包.包括arp,ax25,icmp,tcp, telnet,trace,udp的源代码,可同时作为客户端,服务端 ,ip包路由.同时处理多个服务器,客户端
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ANSI display emulation
 *
 * This file emulates the IBM ANSI terminal display. It maintains a
 * display buffer and descriptor for each virtual display, of which there
 * can be many. All writes occur first into this display buffer, and then
 * any particular display buffer can be copied onto the real screen.
 * This allows many background tasks to run without blocking even though
 * only one task's display is actually being shown.
 *
 * This display driver is substantially faster than even the NANSI.SYS
 * loadable screen driver, particularly when large blocks are written.
 *
 * Extensions to handle displaying multiple small virtual windows should
 * be pretty straightforward.
 *
 * Copyright 1992 Phil Karn, KA9Q
 * 
 */
#include <conio.h>
#include <string.h>
#include <sys/stat.h>
#include "global.h"
#include "display.h"
#include "proc.h"

#define	DCOL	67
#define	DSIZ	(81-DCOL)

uint8 Statbuf[2*COLS];
struct dirty Stdirt;

uint8 fgattr[] = { 0, 4, 2, 14, 1, 5, 3, 7 };	/* Foreground attribs */
uint8 bgattr[] = { 0, 4, 2, 6, 1, 5, 3, 7 };	/* Background attribs */

static void dclrscr(struct display *dp);
static void desc(struct display *dp,uint8 c);
static void darg(struct display *dp,uint8 c);
static void dchar(struct display *dp,uint8 c);
static void dclreol(struct display *dp,int row,int col);
static void dattrib(struct display *dp,int val);
static uint8 *rbufloc(struct display *dp,int row,int col);
static uint8 *vbufloc(struct display *dp,int row,int col);
static void dinsline(struct display *dp);
static void ddelline(struct display *dp);
static void ddelchar(struct display *dp);
static void dinsert(struct display *dp);
static void dclreod(struct display *dp,int row,int col);
static int sadjust(struct display *dp,int lines);


extern struct proc *Display;

/* Create a new virtual display.
 * The "noscrol" flag, if set, causes lines to "wrap around" from the bottom
 * to the top of the screen instead of scrolling the entire screen upwards
 * with each new line. This can be handy for packet trace screens.
 */
struct display *
newdisplay(
int rows,
int cols,	/* Size of new screen. 0,0 defaults to whole screen */
int noscrol,	/* 1: old IBM-style wrapping instead of scrolling */
int size	/* Size of virtual screen, lines */
){
	struct display *dp;
	struct text_info text_info;
	int i;

	gettextinfo(&text_info);
	if(rows == 0)
		rows = text_info.screenheight - 1;/* room for stat line */
	if(cols == 0)
		cols = text_info.screenwidth;

	dp = (struct display *)calloc(1,sizeof(struct display) +
	 (rows+1)*sizeof(struct dirty) + cols);
	dp->cookie = D_COOKIE;
	dp->buf = calloc(2,cols*size);
	dp->dirty = (struct dirty *)(dp + 1);
	dp->tabstops = (uint8 *)(dp->dirty + rows);
	dp->rows = rows;
	dp->cols = cols;
	dp->virttop = dp->realtop = 0;
	dp->size = size;

	/* Set default tabs every 8 columns */
	for(i=0;i<cols;i+= 8)
		dp->tabstops[i] = 1;

	dp->attrib = 0x7;	/* White on black, no blink or intensity */
	dclrscr(dp);		/* Start with a clean slate */
	dp->flags.dirty_cursor = 1;
	dp->flags.no_scroll = noscrol;

	return dp;
}

/* Close a display - simply get rid of the memory */
void
closedisplay(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;
	free(dp->buf);
	free(dp);
}

/* Write buffer to status line. Works independently of the ANSI
 * machinery so as to not upset a possible escape sequence in
 * progress. Maximum of one line allowed, no control sequences
 */
void
statwrite(
int col,		/* Starting column of write */
void *buf,		/* Data to be written */
int cnt,		/* Count */
int attrib		/* Screen attribute to be used */
){
	uint8 *buf1 = buf;
	uint8 *sp = Statbuf;

	/* Clip debug area if activated */
	if(Kdebug && cnt > DCOL - col - 1)
		cnt = DCOL - col - 1;
	else if(cnt > COLS-col)
		cnt = COLS - col;	/* Limit write to line length */

	while(cnt-- != 0){
		if(sp[0] != *buf1 || sp[1] != attrib){
			if(col < Stdirt.lcol)
				Stdirt.lcol = col; 
			if(col > Stdirt.rcol)
				Stdirt.rcol = col;
			sp[0] = *buf1;
			sp[1] = attrib;
		}
		buf1++;
		sp += 2;
		col++;
	}
	/* Display unscrolled status region */
	if(Stdirt.lcol <= Stdirt.rcol){
		puttext(Stdirt.lcol+1,ROWS,Stdirt.rcol+1,ROWS,
		 Statbuf + 2*Stdirt.lcol);
		Stdirt.lcol = COLS-1;
		Stdirt.rcol = 0;
	}
}
/* Write data to the virtual display. Does NOT affect the real screen -
 * dupdate(dp) must be called to copy the virtual screen to the real
 * screen.
 */
void
displaywrite(
struct display *dp,	/* Virtual screen pointer */
const void *buf,	/* Data to be written */
int cnt			/* Count */
){
	uint8 c;
	const char *bufp = buf;

	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	while(cnt-- != 0){
		c = *bufp++;
		switch(dp->state){
		case DISP_ESCAPE:
			desc(dp,c);
			break;
		case DISP_ARG:
			darg(dp,c);
			break;
		case DISP_NORMAL:
			dchar(dp,c);
			break;
		}
	}
	ksignal(dp,1);
}
/* Make the real screen look like the virtual one. It attempts to do as
 * little work as possible unless the "dirty screen" flag is set -- then
 * the entire screen is updated. (This is useful when switching between
 * virtual display screens.)
 *
 * Note the different row and column numbering conventions -- I start
 * at zero, the puttext() and gotoxy() library functions start at 1.
 */
void
dupdate(struct display *dp)
{
	int row;
	long sp;
	struct dirty *dirtp;

	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	for(row=0,dirtp=dp->dirty;row<dp->rows;row++,dirtp++){
		if(dp->flags.dirty_screen){
			/* Force display of all columns */
			dirtp->lcol = 0;
			dirtp->rcol = dp->cols-1;
		}
		if(dirtp->lcol <= dirtp->rcol){
			puttext(dirtp->lcol+1,row+1,dirtp->rcol+1,row+1,
			 dp->flags.scrollbk ? rbufloc(dp,row,dirtp->lcol)
				: vbufloc(dp,row,dirtp->lcol));
			dirtp->lcol = dp->cols-1;
			dirtp->rcol = 0;
		}
	}
	if(dp->flags.scrollbk){
		/* Turn off cursor entirely */
		_setcursortype(_NOCURSOR);
	} else 	if(dp->flags.dirty_screen || dp->flags.dirty_cursor){
		/* Update cursor */
		gotoxy(dp->col+1,dp->row+1);
		_setcursortype(_NORMALCURSOR);
	}
	dp->flags.dirty_cursor = 0;
	dp->flags.dirty_screen = 0;
}
void
dscrollmode(
struct display *dp,
int flag
){
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	if(flag != dp->flags.scrollbk){
		dp->flags.scrollbk = flag;
		dp->flags.dirty_screen = 1;
		alert(Display,1);
	}
}

void
dhome(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	sadjust(dp,(dp->size - dp->rows));
}
void
dend(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	if(dp->realtop != dp->virttop){
		dp->realtop = dp->virttop;
		dp->flags.dirty_screen = 1;
		alert(Display,1);
	}
}
void
dpgup(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	sadjust(dp,dp->rows);
}
void
dpgdown(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	sadjust(dp,-dp->rows);
}
void
dcursup(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	sadjust(dp,+1);
}
void
dcursdown(struct display *dp)
{
	if(dp == NULL || dp->cookie != D_COOKIE)
		return;

	sadjust(dp,-1);
}

/* Process incoming character while in ESCAPE state */
static void
desc(struct display *dp,uint8 c)
{
	int i;

	switch(c){
	case 'O':
	case '[':	/* Always second char of ANSI escape sequence */
		/* Get ready for argument list */
		dp->state = DISP_ARG;
		dp->argi = 0;
		for(i=0;i<MAXARGS;i++)
			dp->arg[i] = 0;

		break;
	case '7':	/* Save cursor location (VT-100) */
		dp->savcol = dp->col;
		dp->savrow = dp->row;
		dp->state = DISP_NORMAL;
		break;
	case '8':	/* Restore cursor location (VT-100) */
		dp->col = dp->savcol;
		dp->row = dp->savrow;
		dp->flags.dirty_cursor = 1;
		dp->state = DISP_NORMAL;
		break;
	case ESC:
		break;	/* Remain in ESCAPE state */
	case 'H':	/* Set tab stop at current position (VT-100) */
		dp->tabstops[dp->col] = 1;
		break;
	default:
		dp->state = DISP_NORMAL;
		dchar(dp,c);
	}
}

/* Process characters after a ESC[ sequence */
static void
darg(struct display *dp,uint8 c)
{
	int i;

	switch(c){
	case ESC:
		dp->state = DISP_ESCAPE;
		return;
	case '?':	/* Ignored */
	case '=':
		return;
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		/* Collect decimal number */
		dp->arg[dp->argi] = 10*dp->arg[dp->argi] + (c - '0');
		return;
	case ';':	/* Next argument is beginning */
		if(dp->argi <= MAXARGS - 1)
			dp->argi++;
		dp->arg[dp->argi] = 0;
		return;
	case '@':	/* Open up space for character */
		dinsert(dp);
		break;
	case 'A':	/* Cursor up */
		if(dp->arg[0] == 0)
			dp->arg[0] = 1;	/* Default is one line */
		if(dp->arg[0] <= dp->row)
			dp->row -= dp->arg[0];
		else
			dp->row = 0;
		dp->flags.dirty_cursor = 1;
		break;
	case 'B':	/* Cursor down */
		if(dp->arg[0] == 0)
			dp->arg[0] = 1;	/* Default is one line */
		dp->row += dp->arg[0];
		if(dp->row >= dp->rows)
			dp->row = dp->rows - 1;
		dp->flags.dirty_cursor = 1; 
		break;
	case 'C':	/* Cursor right */
		if(dp->arg[0] == 0)
			dp->arg[0] = 1;	/* Default is one column */
		dp->col += dp->arg[0];
		if(dp->col >= dp->cols)
			dp->col = dp->cols - 1;
		dp->flags.dirty_cursor = 1;
		break;
	case 'D':	/* Cursor left */
		if(dp->arg[0] == 0)

⌨️ 快捷键说明

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