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

📄 eedisp.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International *	This software is quasi-public; it may be used freely with *	like software, but may NOT be sold or made part of licensed *	products without permission of the author. *//* EEDISP	Redisplay and screen image routines */#if 0Note that there are several different types of "efficiency" criteriainvolved with respect to display updating:	(1) Terminal speed: minimize # characters output.	(2) Program speed: minimize CPU time used.	(3) Program size: minimize code and memory usage.	(4) Program modularity: minimize "hooks" between edit/display rtns.The current algorithms necessarily represent a compromise among all ofthese objectives.	The cursor is always located at CUR_DOT in the buffer CUR_BUFof the current window CUR_WIN.  This may not be true during functionexecution, but is always true at the top-level loop of commandexecution and redisplay.  In order to minimize update overhead, thereare various flags or variables that the edit functions can use tocommunicate with "redisplay" and tell it how extensive the updatesreally need to be.	The entire known screen is always represented by a linked listof "windows"; updating the entire screen consists of separatelyupdating every window on the list.  Windows can only be definedhorizontally (as a range of lines), and must not overlap.  Each windowhas a buffer associated with it; the redisplay routines are responsiblefor displaying the contents of this buffer.	The lowest level data structure for the screen consists of anarray of SCR_LINE structures, one for each possible physical screenline.  Each line structure has some flags, and pointers to three differentrepresentations of what should be on the line:	(1) SL_BOFF, SL_LEN - Defines the range of the buffer data which		this screen line should represent.		If the flag SL_EOL is set, this range ends with (and includes)		an EOL character.	(2) SL_LINE, SL_COL - Always keeps a copy of the current physical		screen line image.  Each byte is a character which occupies		only one column position on the screen.		If the flag SL_CSO is set, the line is in standout mode.	(3) SL_NLIN, SL_NCOL - The desired "new" screen line image.		This is only valid if the SL_MOD flag is set for the line,		indicating that these variables are set and point to the		new image of what the screen line should be.		If the flag SL_NSO is set, the new line should be in standout		mode.	Lastly there is a variable SL_CONT, which is needed forcontinuation of too-long logical lines over several physical lines.  IfSL_CONT is:	0 = logical line fits entirely on the screen.		Either SL_EOL is set, or this line is ended by EOF		(end of the buffer).	1 = logical line is too long, but the last buffer char fits		entirely on this physical line.  SL_EOL is never set.	>1 = logical line is too long, and the last buffer char		"overruns" the end of the physical image; that is, part of		its representation is at the end of this line, but the		rest of it is at the start of the next line.  This can		only happen with "big" characters like TAB, ^A, ~^A, etc.		that need more than one column of representation.		There are SL_CONT-1 chars of overrun stored at the		end of SL_LINE (SL_NLIN if SL_MOD is set).		SL_EOL is never set.Note that if a line contains any overrun, and the next line is alsopart of the same window, the next line''s screen image will start withthe SL_CONT-1 chars of overrun, rather than with the representation ofthat line''s first buffer char.	The "EOL" character on Unix systems is normally the new-linecharacter '\n' (ASCII LF).  However, on other systems EOL may beindicated by a two-character CR-LF sequence, with either CR or LF aloneconsidered to be "stray".  For this reason, the buffer flag B_EOLCRLFexists to control handling and display of EOLs.  If the flag is off,the EOL mode is LF, and there are no problems of splitting up characters.If the flag is on, however, the EOL mode is CRLF and the following ruleshold:	EOL is the sequence CR-LF only.	LF without preceding CR is a "stray" LF, displayed as ^J.	CR without following LF is a "stray" CR, displayed as ^M.	Stray LFs and CRs do not terminate a logical line.	"End of Line" as a position is the dot just before the CR of a CR-LF.	"Beg of Line" as a position is the dot just after the LF of a CR-LF.	If the current dot is between a CR and LF, it is positioned at		the beginning of the physical screen line.SL_LINE and SL_COL are always accurate at every stage of processing.The other variables are accurate only after fix_wind has been calledto "fix up" the line structures within a window.  If eitherRD_WINRES or RD_TMOD is set, none of these "other variables" shouldbe depended on.  Any functions which are screen-relative (d_ type)must be sure that fix_wind is called if necessary, and must givepreference to the "new" representation in SL_NLINE and SL_NCOL ifSL_MOD is set.The flag RD_UPDWIN will be set by fix_wind if any lines have beenmodified.  Because fix_wind does not perform any actual display update,it is possible for functions to continue operating on the buffer andscreen image without requiring that changes be displayed until there isnothing else left to do.  The routine upd_wind performs the actualterminal I/O necessary to update all the screen lines which have SL_MODset.  Although the process of updating each line is currentlynon-interruptible, it is possible for upd_wind to interrupt itselfbetween line updates if it detects that user input has happened, and it willreturn with the window only partially updated.  The screen image statewill be completely consistent, however, and the RD_UPDWIN flag willremain set.Communication between the editing functions and the redisplay routinesis limited as much as possible to the flags in the global RD_TYPE.Each window has its own copy of these flags in W_REDP, so that ifwindows are changed, the update hints for that window will bepreserved.  The flags that can be set are listed below.  Those markedwith "*" are global in nature; all others apply only within a singlewindow (normally the current window).* RD_SCREEN - Total refresh.  Clears entire screen and redisplays all	windows.* RD_MODE - Mode line has changed, update it.* RD_CHKALL - Check ALL windows for any redisplay flags, and perform	any updates necessary.  Otherwise only the current (or specified)	window flags are checked.* RD_WINDS - Updates all windows.  Like RD_WINRES applied to all windows.  RD_WINRES - Update window (assume completely changed).  RD_TMOD - Text changed in this window.  The range of changes is	specified by W_BMOD and W_EMOD in combination with W_OLDZ.	Redisplay checking will limit itself to this range.	These vars are set by buf_tmod in the main command loop, and	reset by fix_wind when the window is fixed up.  RD_MOVE - Cursor has moved within current window; may have moved outside	the window.  W_DOT or CUR_DOT specifies where it should be.  RD_ILIN - Hint: Line insert done.  Currently no function sets this.  RD_DLIN - Hint: Line delete done.  Currently no function sets this.Internal flags:  RD_UPDWIN - Window needs updating. Used by fix_wind and upd_wind only.	Set when window has been "fixed up" and at least one screen	line was modified.  RD_FIXWIN - Supposed to mean window needs fixing (via call to fix_wind).	Not really used.Not implemented, may never be, but comments retained:  RD_WINCLR - Clear window (not entire screen)  RD_NEWWIN - Window has moved.  (not needed? Random stuff here)	a. to follow cursor; redisplay selects a new TOPLDOT.	b. randomly; new TOPLDOT furnished, use unless cursor out (then a).	c. find new TOPLDOT as directed (move up/down N screen lines)	For now, assume that (c) doesn''t apply (ie C-V uses (b) and sets	TOPLDOT itself).  So fix_wind selects new one only if cursor	won''t fit.  topldot takes precedence over sl_boff.#endif /*COMMENT*//* Declarations and stuff */#include "elle.h"static int sctr();int trm_mode;	/* 0 = TTY in normal, non-edit mode.		 * 1 = TTY in edit mode.		 * -1 = TTY detached (hung up).		 * This flag is only used by the 3 routines below,		 * plus hup_exit.		 *//* REDP_INIT() - Called once-only at startup to initialize redisplay *	and terminal */redp_init (){	trm_mode = 0;		/* Ensure flag says not in edit mode */	ts_init();		/* Get sys term info, set up stuff */	if (trm_ospeed == 0)	/* Default speed to 9600 if unknown */		trm_ospeed = 13;	t_init();		/* Identify term type, set term-dep stuff */	set_scr();		/* Set up software screen image */	set_tty();		/* Enter editing mode! */	redp(RD_SCREEN|RD_MODE); /* Force full re-display, new mode line */}/* SET_TTY() - Set up terminal modes for editing */set_tty(){	if(trm_mode) return;	/* Ignore if detached or in edit mode */	trm_mode++;	ts_enter();		/* Set up system's ideas about terminal */	t_enter();		/* Set terminal up for editing */}/* CLEAN_EXIT() - Restore original terminal modes. *	Returns previous state. */clean_exit (){	register int prevstate = trm_mode;	if(prevstate > 0)	/* Ignore unless in editing mode */	  {	trm_mode = 0;		t_curpos(scr_ht-1, 0);	/* Go to screen bottom */		t_exit();		/* Clean up the terminal */		tbufls();		/* Force out all buffered output */		ts_exit();		/* Restore system's old term state */#if ! IMAGEN		writez(1,"\n");		/* Get fresh line using OS output */#endif /*-IMAGEN*/	  }	return prevstate;}/* SET_SCR() - Allocate screen image, set up screenline pointer table */set_scr(){	register struct scr_line **scrp, *stp;	register scrsiz;	char *sbuf;	scr_wd0 = scr_wid - 1;	scrsiz = scr_ht*(scr_wid+MAXCHAR);	if(  scr_ht  > MAXHT || scr_wid > MAXLINE)	  {	clean_exit();		printf("ELLE: %dx%d screen too big\n",scr_ht,scr_wid);		exit(1);	  }	if((stp = (struct scr_line *) calloc(scr_ht*sizeof(struct scr_line)							 + scrsiz*2,1)) == 0)	  {	clean_exit();		printf("ELLE: not enough memory\n");		exit(1);	  }	sbuf = (char *)stp + scr_ht*sizeof(struct scr_line);	for(scrp = &scr[0]; scrp < &scr[scr_ht]; sbuf += scr_wid+MAXCHAR)	  {	stp->sl_line = sbuf;		stp->sl_nlin = sbuf + scrsiz;		*scrp++ = stp++;	  }}/* REDISPLAY() *	Main function of redisplay routines.  Called every time ELLE * forces update of the terminal screen.  "rd_type" contains hints * as to what has changed or needs updating, to avoid wasting time * on things which don't need attention. */redisplay (){	register struct window *w;	register i;	struct window *make_mode();	w = cur_win;	w->w_redp |= rd_type&RDS_WINFLGS;	/* Set cur_win's flags */	rd_type &= ~RDS_WINFLGS;		/* Leave only globals */	if (rd_type & RD_SCREEN)		/* Clear and refresh? */	  {		t_clear ();			/* Clear the screen */		for(i = scr_ht; --i >= 0;)	/* Clear screen image */			scr[i]->sl_col = 0;		if(w != ask_win)		/* If not in ask-window */		  {	chg_win(ask_win);			e_reset();		/* Then flush its contents */			chg_win(w);		  }		redp(RD_WINDS);		/* Update all windows */		rd_type &= ~RD_SCREEN;	/* If redisplay is interrupted, */					/* don't do it all over again */	  }	if (rd_type & RD_WINDS)		/* Update all windows? */	  {	redp(RD_CHKALL);		for (w = win_head; w; w = w -> w_next)	/* For each win */			w->w_redp |= RD_WINRES;		rd_type &= ~RD_WINDS;	  }	if (rd_type & RD_CHKALL)	/* Check all windows for changes? */	  {	for (w = win_head; w; w = w->w_next)	/* For each win */		    if(!(w->w_flags&W_MODE))		/* skip mode wins */			if(w->w_redp && upd_wind(w))				return;		/* May be interrupted */	  }	/* See if ask-window needs updating (to avoid RD_CHKALL in SAY) */	if((w = ask_win)->w_redp && upd_wind(w))		return;				/* May be interrupted */	/* Check current window for changes */	if((w = cur_win)->w_redp && upd_wind(w))		return;				/* May be interrupted */	/* Now update mode line(s) if necessary */	if(rd_type&RD_MODE)	  {		fupd_wind(w = make_mode(user_win));#if FX_2MODEWINDS		if (sep_win			/* If 2 windows */		  && (sep_win->w_flags&W_MODE)	/* and 2 mode windows */		  && (sep_win->w_redp || mode_win->w_redp))	/* Check */			fupd_wind(make_mode(oth_win));	/* Must update both */#endif	  }	/* Finally, leave cursor in right place. */	if(upd_curs(cur_dot)==0)		/* If something screwed up, */		errbarf("Cursor out of window");	/* Complain, */						/* and leave cursor at bot */	rd_type = 0;	tbufls();		/* Force out all terminal output */}fupd_wind(w)		/* Force window update */register struct window *w;{	w->w_redp |= RD_WINRES;	if(fix_wind(w))		upd_wind(w);}/* * UPD_CURS *	Move screen cursor to position of specified dot within current window. *	Returns 0 if dot was not within window (and cursor was not moved), *	otherwise returns 1 for success. */upd_curs(adot)chroff adot;{	register struct scr_line *s;	register int y, x;	chroff savdot;	if((y = d_line(adot)) < 0)		return(0);	/* Fail, not within window */	s = scr[y];		/* Now have line that dot is on */	/* Get proper offset for any continuation chars from prev line */	if(y > cur_win->w_pos)	  {	if((x = scr[y-1]->sl_cont) > 0)			x--;	  }	else x = 0;	savdot = e_dot();	e_go(s->sl_boff);	if((x = d_ncols((int)(adot - s->sl_boff),x)) < 0)	  {	/* If lost, assume it's because we are just after a char		** which has its representation continued onto next line.		** Move cursor to end of that continuation.		** d_line should have ensured that this is safe, but		** we double-check just to make sure.		*/		if((x = s->sl_cont) > 0)	/* Set X to end of cont */			--x;						/* and on next line down */		if(++y >= (cur_win->w_pos + cur_win->w_ht))		  {	e_go(savdot);		/* Failed, below window */			return(0);		  }	  }	e_go(savdot);	t_move(y, x);		/* Move cursor cleverly */	return(1);		/* Return success! */}/* Return line # for given dot, -1 if out of current window */d_line(cdot)chroff cdot;{	register struct scr_line *s;	register struct window *w;	register int i;	chroff savdot;	int bot;	w = cur_win;	i = w->w_pos;	bot = i + w->w_ht;	for(; i < bot; i++)	  {	s = scr[i];		if(cdot <= s->sl_boff)			goto gotl;	  }	/* End of window, repeat test specially for last line */	savdot = s->sl_boff + (chroff)s->sl_len;	if(cdot > savdot)	/* If past last char of last line */		return(-1);	/* then clearly outside */	--i;			/* Make i match s (bottom line) */	if(savdot != cdot)	/* If not exactly at end */		return(i);	/* Then we're inside for sure */	goto linbet;gotl:	if(s->sl_boff != cdot)	/* Are we on line boundary? */	  {	if(i <= w->w_pos)	/* No, off top of window? */			return(-1);	/* Above top, out for sure */		return(--i);	  }	/* Here, dot is exactly on line boundary, have to decide which	 * line it really belongs to.	 * Get S = pointer to line which cursor is at the end of.	 */	if(i <= w->w_pos)	/* Quick chk of trivial case, empty buffer */		return(i);	s = scr[--i];linbet:	if((s->sl_flg&SL_EOL)	/* If line has LF */	  || (s->sl_cont > 1))	/* or a continued char */		if(++i >= bot)		/* Then cursor is on next line */			return(-1);	return(i);}/* D_NCOLS - auxiliary for UPD_CURS.  (also called by indtion() in EEFD)**	 We are positioned at a place in the current buffer corresponding to** the beginning of the screen line, and given:**	lcnt - # of chars in buffer to move forward over**	ccol - current column position** Returns the new column position.  There are some special cases:**	Hits EOF: returns normally (new column position)**	Hits EOL: returns -1**	Position is past end of screen: returns -1** The buffer position has changed, but this is irrelevant as upd_curs** restores it just after the call.*/d_ncols(lcnt, ccol)

⌨️ 快捷键说明

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