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

📄 display.c

📁 操作系统源代码
💻 C
字号:
/* Copyright (c) 1985 Ceriel J.H. Jacobs */# ifndef lintstatic char rcsid[] = "$Header: display.c,v 7.3 90/03/05 16:57:39 ceriel Exp $";# endif# define _DISPLAY_# include "in_all.h"# include "display.h"# include "assert.h"# include "machine.h"# include "term.h"# include "output.h"# include "options.h"# include "process.h"# include "getline.h"# include "main.h"STATIC char * do_line();/* * Fill n lines of the screen, each with "str". */STATIC VOIDfillscr(n,str) char *str; int n; {	while (n-- > 0) {		putline(str);	}}/* * Skip "n" screenlines of line "p", and return what's left of it. */STATIC char *skiplines(p,n) char *p; int n; {	while (n-- > 0) {		p = do_line(p,0);		scr_info.currentpos--;	}	return p;}/* * Redraw screen. * "n" = 1 if it is a real redraw, 0 if one page must be displayed. * It is also called when yap receives a stop signal. */VOIDredraw(n) int n; {	register struct scr_info *p = &scr_info;	register int i;	i = pagesize;	if (n && p->currentpos) {		i = p->currentpos;	}	(VOID) display(p->firstline,p->nf,i,1);}/* * Compute return value for the routines "display" and "scrollf". * This return value indicates wether we are at the end of file * or at the start, or both. * "s" contains that part of the last line that was not displayed. */STATIC intcompretval(s) char *s; {	register int i;	register struct scr_info *p = &scr_info;	i = 0;	if (!s || (!*s && !getline(p->lastline+1, 1))) {		i = EOFILE;	}	if (p->firstline == 1 && !p->nf) {		i |= START;	}	status = i;	return i;}/* * Display nlines, starting at line n, not displaying the first * nd screenlines of n. * If reallydispl = 0, the actual displaying is not performed, * only the computing associated with it is done. */intdisplay(n,nd,nlines,reallydispl)  long n; int nd; register int nlines; int reallydispl; {	register struct scr_info *s = &scr_info;	register char *p;	/* pointer to line to be displayed */	if (startcomm)	{	/* No displaying on a command from the				 * yap command line. In this case, displaying				 * will be done after executing the command,				 * by a redraw.				 */		reallydispl = 0;	}	if (!n) {		n = 1L;		nd = 0;	}	if (reallydispl) {	/* move cursor to starting point */		if (stupid) {			putline(currentfile);			putline(", line ");			prnum(n);			nlines--;		}		if (cflag) {			putline("\r\n");		}		else {			home();			clrscreen();		}	}	/*	 * Now, do computations and display	 */	s->currentpos = 0;	s->nf = nd;	s->head = s->tail;	s->tail->cnt = 0;	s->tail->line = n;	p = skiplines(getline(n,1),nd);	while (nlines && p) {		/*		 * While there is room,		 * and there is something left to display ...		 */		(s->tail->cnt)++;		nlines--;		if (*(p = do_line(p,reallydispl)) == '\0') {			/*			 * File-line finished, get next one ...			 */			p = getline(++n,1);			if (nlines && p) {				s->tail = s->tail->next;				s->tail->cnt = 0;				s->tail->line = n;			}		}	}	if (!stupid) {		s->currentpos += nlines;		if (reallydispl) {			fillscr(nlines, "~\r\n");			fillscr(maxpagesize - s->currentpos, "\r\n");		}	}	return compretval(p);}/* * Scroll forwards n lines. */intscrollf(n,reallydispl) int n; int reallydispl; {	register struct scr_info *s = &scr_info;	register char *p;	register long ll;	register int i;	/*	 * First, find out how many screenlines of the last line were already	 * on the screen, and possibly above it.	 */	if (n <= 0 || (status & EOFILE)) return status;	if (startcomm) reallydispl = 0;	/*	 * Find out where to begin displaying	 */	i = s->tail->cnt;	if ((ll = s->lastline) == s->firstline) i += s->nf;	p = skiplines(getline(ll, 1), i);	/*	 * Now, place the cursor at the first free line	 */	if (reallydispl && !stupid) {		clrbline();		mgoto(s->currentpos);	}	/*	 * Now display lines, keeping track of which lines are on the screen.	 */	while (n-- > 0) {	/* There are still rows to be displayed */		if (!*p) {	/* End of line, get next one */			if (!(p = getline(++ll, 1))) {				/*				 * No lines left. At end of file				 */				break;			}			s->tail = s->tail->next;			s->tail->cnt = 0;			s->tail->line = ll;		}		if (s->currentpos >= maxpagesize) {			/*			 * No room, delete first screen-line			 */			s->currentpos--;			s->nf++;			if (--(s->head->cnt) == 0) {				/*				 * The first file-line on the screen is wiped				 * out completely; update administration				 * accordingly.				 */				s->nf = 0;				s->head = s->head->next;				assert(s->head->cnt > 0);			}		}		s->tail->cnt++;		p = do_line(p, reallydispl);	}	return compretval(p);}/* * Scroll back n lines */intscrollb(n, reallydispl) int n, reallydispl; {	register struct scr_info *s = &scr_info;	register char *p;	/* Holds string to be displayed */	register int i;	register int count;	register long ln;	/* a line number */	register int nodispl;	int cannotscroll;	/* stupid or no insert-line */	/*	 * First, find out where to start	 */	if ((count = n) <= 0 || (status & START)) return status;	if (startcomm) reallydispl = 0;	cannotscroll = stupid || (!*AL && !*SR);	ln = s->firstline;	nodispl = s->nf;	while (count) { /* While scrolling back ... */		if (i = nodispl) {			/*			 * There were screen-lines of s->firstline that were not			 * displayed.			 * We can use them now, but only "count" of them.			 */			if (i > count) i = count;			s->currentpos += i;			nodispl -= i;			count -= i;		}		else {	/* Get previous line */			if (ln == 1) break; /* isn't there ... */			p = getline(--ln, 1);			/*			 * Make it the first line of the screen and compute			 * how many screenlines it takes. These lines are not			 * displayed, but nodispl is set to this count, so			 * that it will be nonzero next time around			 */			nodispl = 0;			do {	/* Find out how many screenlines */				nodispl++;				p = skiplines(p, 1);			} while (*p);		}	}	n -= count;	if ((i = s->currentpos) > maxpagesize) i = maxpagesize;	if (reallydispl && hardcopy) i = n;	/*	 * Now that we know where to start, we can use "display" to do the	 * rest of the computing for us, and maybe even the displaying ...	 */	i = display(ln,		    nodispl,		    i,		    reallydispl && cannotscroll);	if (cannotscroll || !reallydispl) {		/*		 * Yes, "display" did the displaying, or we did'nt have to		 * display at all.		 * I like it, but the user obviously does not.		 * Let him buy another (smarter) terminal ...		 */		return i;	}	/*	 * Now, all we have to do is the displaying. And we are dealing with	 * a smart terminal (it can insert lines or scroll back).	 */	home();	/*	 * Insert lines all at once	 */	for (i = n; i; i--) {		if (DB && *CE) {			/*			 * Grumble..., terminal retains lines below, so we have			 * to clear the lines that we push off the screen			 */			clrbline();			home();		}		if (*SR) {			scrollreverse();		}		else {# ifdef VT100_PATCH			insert_line(0);# else			insert_line();# endif		}	}	p = skiplines(getline(ln = s->firstline, 1), s->nf);	for (i = 0; i < n; i++) {		p = do_line(p,1);		s->currentpos--;		if (!*p) {			p = getline(++ln, 1);		}	}	return count;}/* * Process a line. * If reallydispl > 0 then display it. */STATIC char *do_line(str, reallydispl) register char *str; int reallydispl; {	char buf[1024];	register char *p = buf;	register int pos = COLS;	register int c;	register int c1;	register int do_ul = 0, do_hl = 0;	int lastmode = 0, lasthlmode = 0;	int c2;	while (*str && pos > 0) {		if (*str < ' ' && (c1 = match(str,&c2,sppat)) > 0) {			/*			 * We found a string that matches, and thus must be			 * echoed literally			 */			if ((pos - c2) <= 0) {				/*				 * It did not fit				 */				break;			}			pos -= c2;			str += c1;			if (reallydispl) {				c = *str;				*p = *str = 0;				cputline(p = buf);				putline(str - c1);				*str = c;			}			continue;		}		c = *str++;		do_hl = 0;		if (*str == '\b' && *(str+1) != 0					&& (c != '_' || *(str+2) == '\b')) {			while (*str == '\b' && *(str+1) != 0) {				str++;				c = *str++;				do_hl = 1;			}		}		do_ul = 1;		/*		 * Find underline sequences ...		 */		if (c == '_' && *str == '\b') {			str++;			c = *str++;		}		else {			if (*str == '\b' && *(str+1) == '_') {				str += 2;			}			else	do_ul = 0;		}		if (reallydispl && do_hl != lasthlmode) {			*p = 0;			cputline(p = buf);			if (do_hl) bold();			else end_bold();		}		lasthlmode = do_hl;		if (reallydispl && do_ul != lastmode) {			*p = 0;			cputline(p = buf);			if (do_ul) underline();			else end_underline();		}		lastmode = do_ul;		*p++ = c;		if (c >= ' ' && c < 0177) {			pos--;			if (reallydispl && do_ul && *UC && pos > 0) {				/*				 * Underlining apparently is done one				 * character at a time.				 */				*p = 0;				cputline(p = buf);				backspace();				underchar();			}			continue;		}		if (c == '\t') {			p--;			c1 = 8 - ((COLS - pos) & 07);			/*			 * Actually, if COLS is a multiple of 8, this can be			 * simplified to			 *     c1 = pos & 07;			 * But of course, we don't know that for sure.			 */			if (pos - c1 < 0) break;			pos -= c1;			if (reallydispl) {				if (expandtabs) {					/*					 * Expand tabs. We cannot let the					 * kernel take care of this					 * for two reasons:					 * 1. There can be tabs in cursor					 *    addressing strings,					 * 2. We probably do it better.					 */					while (c1-- > 0) {						*p++ = ' ';					}				}				else {					*p = 0;					cputline(p = buf);					givetab();				}			}			continue;		}		/*		 * Now we have a control character, which takes two positions		 */		if (pos <= 1) {			p--;			break;		}		pos -= 2;	}	if (reallydispl) {		*p = 0;		cputline(buf);		if (pos > 0 || (pos <= 0 && (!AM || XN))) {			putline("\r\n");		}		/*		 * The next should be here! I.e. it may not be before printing		 * the newline. This has to do with XN. We don't know exactly		 * WHEN the terminal will stop ignoring the newline.		 * I have for example a terminal (Ampex a230) that will		 * continue to ignore the newline after a clear to end of line		 * sequence, but not after an end_underline sequence.		 */		if (do_ul) {			end_underline();		}		if (do_hl) {			standend();		}	}	scr_info.currentpos++;	return str;}/* ARGSUSED */intsetmark(cnt) long cnt; {	/* Set a mark on the current page */	register struct scr_info *p = &scr_info;	p->savfirst = p->firstline;	p->savnf = p->nf;}/* ARGSUSED */inttomark(cnt) long cnt; {		/* Go to the mark */	register struct scr_info *p = &scr_info;	(VOID) display(p->savfirst,p->savnf,pagesize,1);}/* ARGSUSED */intexgmark(cnt) long cnt; {	/* Exchange mark and current page */	register struct scr_info *p = &scr_info;	register long svfirst;	register int svnf;	svfirst = p->firstline;	svnf = p->nf;	tomark(0L);	p->savfirst = svfirst;	p->savnf = svnf;}VOIDd_clean() {			/* Clean up */	register struct scr_info *p = &scr_info;	p->savnf = 0;	p->savfirst = 0;	p->head = p->tail;	p->head->line = 0;	p->currentpos = 0;}

⌨️ 快捷键说明

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