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

📄 curses.c

📁 GEEKOS是一个免费的操作系统内核
💻 C
字号:
/* * Curses emulation for GeekOS * Copyright (c) 2004, David H. Hovemeyer <daveho@cs.umd.edu> * $Revision: 1.3 $ *  * This is free software.  You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */#include <limits.h>#include <conio.h>#include <process.h>#include <fileio.h>#include <curses.h>/* * Notes: * - We can generally avoid redrawing parts of the screen *   that haven't been modified, even when the app eagerly redraws *   things (the "ae" editor does this) * - Scrolling in untested, but should work (I think) * * TODO: * - Buffer the output in refresh(), to avoid making one system *   call for each output character. * - Eliminate struct Screen - we should use two WINDOW objects *   (which is what real curses does) *//* ---------------------------------------------------------------------- * Private functions and data * ---------------------------------------------------------------------- */#define MAXLINES 25#define MAXCOLS 80/* End of line marker */#define EOL 0struct Line {    int buf[MAXCOLS];    bool modified;};struct Screen {    struct Line lines[MAXLINES];    int y, x;};struct _Window {    struct Screen display;	/* The real screen image */    struct Screen work;		/* How we want the screen to appear */    int nScroll;		/* Num lines scrolled since last update */};#define WORK(pwin) (&(pwin)->work)#define DISPLAY(pwin) (&(pwin)->display)#define X(scr) ((scr)->x)#define Y(scr) ((scr)->y)#define LINE(scr,y)  (&((scr)->lines[(y)]))#define CURLINE(scr) LINE(scr,Y(scr))static WINDOW s_stdscr;static __inline__ int Move_Coord(int c, int limit){    if (c < 0)	return 0;    if (c >= limit)	return limit - 1;    return c;}static void Scroll_Screen(struct Screen *s){    int j;    struct Line *last = LINE(s, LINES-1);    for (j = 1; j < LINES; ++j)	*(LINE(s, j-1)) = *(LINE(s, j));    last->buf[0] = EOL;    last->modified = false;}static void Scroll_Win(WINDOW *w){    Scroll_Screen(WORK(w));    ++w->nScroll;}static void Paint_Char(struct Line *line, int x, int c){    int orig = line->buf[x];    line->buf[x] = c;    if (c != orig)	line->modified = true;}/* * Set a character or end of line marker without * updating the cursor.  Updates end of line marker * if required. */static void Set_Char(WINDOW *w, int y, int x, int c){    struct Screen *s = WORK(w);    struct Line *line = LINE(s, y);    int i, eol = INT_MAX;    for (i = 0; i < COLS; ++i) {	if (line->buf[i] == EOL) {	    eol = i;	    break;	}    }    for (i = eol; i < x; ++i)	Paint_Char(line,i,' ');    Paint_Char(line,x,c);    if (eol < x+1 && x < LINES-1)	Paint_Char(line,x+1,EOL);}/* * New line, and return to column 0. */static void Newline(WINDOW *w){    struct Screen *s = WORK(w);    Set_Char(w,Y(s),X(s),EOL);    if (Y(s) == LINES-1)	Scroll_Win(w);    else	Y(s) = Y(s) + 1;    X(s) = 0;}/* * Set a character at current cursor position, * updating the cursor and scrolling as required. */static void Add_Char(WINDOW *w, int c){    struct Screen *s = WORK(w);    if (c == '\n') {	Newline(w);    } else if (c == '\t') {	int nspace = 8 - (X(s) & 7);	if (X(s) + nspace >= COLS) {	    Newline(w);	} else {	    while(nspace-- > 0)		Add_Char(w, ' ');	}    } else if (c == '\r') {	X(s) = 0;    } else if (c >= 1 && c <= 26) {	Add_Char(w,'^');	Add_Char(w,(c-1) + 'A');    } else {	Set_Char(w, Y(s), X(s), c);	if (X(s) == COLS-1)	    Newline(w);	else	   X(s) = X(s) + 1;    }}/* Invalidate entire window. */static void Invalidate(WINDOW *w){    struct Screen *s = WORK(w);    int j;    for (j = 0; j < LINES; ++j)	LINE(s,j)->modified = true;}/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- */WINDOW *stdscr = &s_stdscr;int LINES = 25;int COLS = 80;int clear(void){    int j;    for (j = 0; j < LINES; ++j) {	move(j, 0);	clrtoeol();    }    move(0,0);    return OK;}int getch(void) {    return Get_Key();}int move(int y, int x) {    struct Screen *s = WORK(stdscr);    Y(s) = Move_Coord(y, LINES);    X(s) = Move_Coord(x, COLS);    return OK;}int addch(int c) {    Add_Char(stdscr, c);    return OK;}int clrtoeol(void) {    struct Screen *s = WORK(stdscr);    Set_Char(stdscr, Y(s), X(s), EOL);    return OK;}int clrtobot(void){    struct Screen *s = WORK(stdscr);    int j;    clrtoeol();    for (j = Y(s) + 1; j < LINES; ++j)	Set_Char(stdscr, j, 0, EOL);    return OK;}int mvaddstr(int y, int x, const char *s){    move(y, x);    while (*s != '\0')	addch(*s++);    return OK;}/* * Here is the complicated part - take the working screen image * and find a way to update the real screen to match, * trying to avoid unnecessary output. */int refresh(void){    int i, j;    struct Screen *work = WORK(stdscr), *display = DISPLAY(stdscr);    /*     * Scroll as needed.     */    if (stdscr->nScroll > 0) {	Put_Cursor(LINES-1,0);	while (stdscr->nScroll-- > 0) {	    Put_Char('\n');	    Scroll_Screen(display);	}    }    /*     * Update each modified line     */    for (j = 0; j < LINES; ++j) {	struct Line *workLine = LINE(WORK(stdscr), j);	struct Line *displayLine = LINE(DISPLAY(stdscr), j);	if (workLine->modified) {	    bool identical = true;	    for (i = 0; i < COLS; ++i) {		int ch = workLine->buf[i];		if(ch == EOL) {		    displayLine->buf[i] = EOL;		    break;		}		/* Avoid redrawing the identical prefix of the line */		if (identical) {		    if (workLine->buf[i] == displayLine->buf[i])			continue;		    Put_Cursor(j, i);		    identical = false;		}		displayLine->buf[i] = ch;		Put_Char(ch);	    }	    if (identical)		Put_Cursor(j, i);	    Print("\x1B[K");/* Clear to EOL */	    workLine->modified = false;	}    }    /*     * Update cursor position.     */    Put_Cursor(Y(work), X(work));    Y(display) = Y(work);    X(display) = X(work);    return OK;}WINDOW *initscr(void){    clear();    Invalidate(stdscr);    return stdscr;}int raw(void){    return OK;}int noecho(void){    return OK;}int idlok(WINDOW *w, bool bf){    return OK;}int endwin(void){    move(LINES-1,0);    clrtoeol();    refresh();    return OK;}

⌨️ 快捷键说明

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