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

📄 disp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE * * is provided to you without charge, and with no warranty.  You may give  * * away copies of JOVE, including sources, provided that this notice is    * * included in all the files.                                              * ***************************************************************************/#include "jove.h"#include "ctype.h"#include "termcap.h"#include "chars.h"#include "fp.h"#include "disp.h"#ifdef	IPROCS# include "iproc.h"#endif#ifdef	MAC# include "mac.h"#else# ifdef	STDARGS#  include <stdarg.h># else#  include <varargs.h># endif# include <sys/stat.h>#endif#ifdef MSDOS#define SIGHUP 99#endif#include <signal.h>private void#ifdef	ID_CHAR	DeTab proto((int, char *, char *, size_t, int)),	DelChar proto((int, int, int)),	InsChar proto((int, int, int, char *)),#endif	DoIDline proto((int)),	do_cl_eol proto((int)),	ModeLine proto((Window *)),	GotoDot proto((void)),	UpdLine proto((int)),	UpdWindow proto((Window *, int));#ifdef	MSDOSextern void	dobell proto((int x));#elseprivate void	dobell proto((int x));#endif#ifdef	ID_CHARprivate bool	IDchar proto ((char *, int, int)),	OkayDelete proto ((int, int, int)),	OkayInsert proto ((int, int));private int	NumSimilar proto ((char *, char *, int)),	IDcomp proto ((char *, char *, int));#endifprivate int	AddLines proto((int, int)),	DelLines proto((int, int));int	DisabledRedisplay = NO;/* Kludge windows gets called by the routines that delete lines from the   buffer.  If the w->w_line or w->w_top are deleted and this procedure   is not called, the redisplay routine will barf. */voidChkWindows(line1, line2)Line	*line1,	*line2;{	register Window	*w = fwind;	register Line	*lp,			*lend = line2->l_next;	do {		if (w->w_bufp == curbuf) {			for (lp = line1->l_next; lp != lend; lp = lp->l_next) {				if (lp == w->w_top)					w->w_flags |= W_TOPGONE;				if (lp == w->w_line)					w->w_flags |= W_CURGONE;			}		}		w = w->w_next;	} while (w != fwind);}/* Deleted and killed Lines are about to be recycled: check for dangling refs */voidChkWinLines(){	register Window	*w = fwind;	do {		if (w->w_top == NULL || w->w_top->l_dline == NULL_DADDR)			w->w_flags |= W_TOPGONE;		if (w->w_line == NULL || w->w_line->l_dline == NULL_DADDR)			w->w_flags |= W_CURGONE;		w = w->w_next;	} while (w != fwind);}private bool	RingBell;	/* So if we have a lot of errors ...				  ring the bell only ONCE */voidredisplay(){	register Window	*w = fwind;	int	lineno,		done_ID = NO,		i;	register struct scrimage	*des_p,					*phys_p;	if (DisabledRedisplay == YES)		return;	curwind->w_line = curwind->w_bufp->b_dot;	curwind->w_char = curwind->w_bufp->b_char;#ifdef	MAC	InputPending = NO;#else	if ((InputPending = charp()) != NO)	/* calls CheckEvent, which could */		return;	/* result in a call to rediplay(). We don't want that. */#endif#ifdef	BSD_SIGS	if (UpdFreq)		SigHold(SIGALRM);#endif	if (RingBell) {		dobell(1);		RingBell = NO;	}	AbortCnt = BufSize;		/* initialize this now */	if (UpdMesg)		DrawMesg(YES);	for (lineno = 0, w = fwind; lineno < ILI; w = w->w_next) {		UpdWindow(w, lineno);		lineno += w->w_height;	}	UpdModLine = NO;/* Now that we've called update window, we can			   assume that the modeline will be updated.  But			   if while redrawing the modeline the user types			   a character, ModeLine() is free to set this on			   again so that the modeline will be fully drawn			   at the next redisplay. */	des_p = DesiredScreen;	phys_p = PhysScreen;	for (i = 0; i < ILI; i++, des_p++, phys_p++) {		if (!done_ID && (des_p->s_id != phys_p->s_id)) {			DoIDline(i);			done_ID = YES;		}		if ((des_p->s_flags & (DIRTY | L_MOD)) ||		    (des_p->s_id != phys_p->s_id) ||		    (des_p->s_vln != phys_p->s_vln) ||		    (des_p->s_offset != phys_p->s_offset))			UpdLine(i);		if (InputPending)			goto ret;	}	if (Asking) {		Placur(LI - 1, min(CO - 2, calc_pos(mesgbuf, AskingWidth)));			/* Nice kludge */		flushscreen();	} else {		GotoDot();	}ret:    ;	/* yuck */#ifdef	BSD_SIGS	if (UpdFreq)		SigRelse(SIGALRM);#endif#ifdef	MAC	if (Windchange)		docontrols();#endif	/* MAC */}#ifndef	IBMPCprivate voiddobell(n)int	n;{	while (--n >= 0) {#ifndef	MAC		if (VisBell && VB)			putstr(VB);		else			putpad(BL, 1);#else		SysBeep(5);#endif	}	flushscreen();}#endif	/* IBMPC *//* find_pos() returns the position on the line, that C_CHAR represents   in LINE */private intfind_pos(line, c_char)Line	*line;int	c_char;{	return calc_pos(lcontents(line), c_char);}intcalc_pos(lp, c_char)register char	*lp;register int	c_char;{	register int	pos = 0;	register int	c;	while ((--c_char >= 0) && ((c = *lp++) & CHARMASK) != 0) {		if (c == '\t')			pos += (tabstop - (pos % tabstop));		else if (jiscntrl(c))			pos += 2;		else			pos += 1;	}	return pos;}bool	UpdModLine = NO,	UpdMesg = NO;private voidDoIDline(start)int	start;{	register struct scrimage	*des_p = &DesiredScreen[start];	struct scrimage	*phys_p = &PhysScreen[start];	register int	i,			j;	/* Some changes have been made.  Try for insert or delete lines.	   If either case has happened, Addlines and/or DelLines will do	   necessary scrolling, also CONVERTING PhysScreen to account for the	   physical changes.  The comparison continues from where the	   insertion/deletion takes place; this doesn't happen very often,	   usually it happens with more than one window with the same	   buffer. */	if (!CanScroll)		return;		/* We should never have been called! */	for (i = start; i < ILI; i++, des_p++, phys_p++)		if (des_p->s_id != phys_p->s_id)			break;	for (; i < ILI; i++) {		for (j = i + 1; j < ILI; j++) {			des_p = &DesiredScreen[j];			phys_p = &PhysScreen[j];			if (des_p->s_id != 0 && des_p->s_id == phys_p->s_id)				break;			if (des_p->s_id == PhysScreen[i].s_id) {				if (des_p->s_id == 0)					continue;				if (AddLines(i, j - i)) {					DoIDline(j);					return;				}				break;			}			if ((des_p = &DesiredScreen[i])->s_id == phys_p->s_id) {				if (des_p->s_id == 0)					continue;				if (DelLines(i, j - i)) {					DoIDline(i);					return;				}				break;			}		}	}}/* Make DesiredScreen reflect what the screen should look like when we are done   with the redisplay.  This deals with horizontal scrolling.  Also makes   sure the current line of the Window is in the window. */bool	ScrollAll = NO;private voidUpdWindow(w, start)register Window	*w;int	start;{	Line	*lp;	int	i,		upper,		/* top of window */		lower,		/* bottom of window */		strt_col,	/* starting print column of current line */		ntries = 0;	/* # of tries at updating window */	register struct scrimage	*des_p,					*phys_p;	Buffer	*bp = w->w_bufp;retry:	if (w->w_flags & W_CURGONE) {		w->w_line = bp->b_dot;		w->w_char = bp->b_char;	}	if (w->w_flags & W_TOPGONE)		CentWind(w);	/* reset topline of screen */	w->w_flags &= ~(W_CURGONE | W_TOPGONE);	/* make sure that the current line is in the window */	upper = start;	lower = upper + w->w_height - 1;	/* don't include modeline */	for (i = upper, lp = w->w_top; i < lower && lp != NULL; lp = lp->l_next, i++)		if (lp == w->w_line)			break;	if (i == lower || lp == NULL) {		ntries += 1;		if (ntries == 1) {			CalcWind(w);			goto retry;		} else if (ntries == 2) {			w->w_top = w->w_line = w->w_bufp->b_first;			writef("\rERROR in redisplay: I got hopelessly lost!");			dobell(2);			goto retry;		} else if (ntries == 3) {			writef("\n\rOops, still lost, quitting ...\r\n");			finish(SIGHUP);		}	}	/* first do some calculations for the current line */	{		int	diff = (w->w_flags & W_NUMLINES) ? 8 : 0,			end_col;		strt_col = ScrollAll? w->w_LRscroll : PhysScreen[i].s_offset;		end_col = strt_col + (CO - 2) - diff;		/* Right now we are displaying from strt_col to		   end_col of the buffer line.  These are PRINT		   columns, not actual characters. */		w->w_dotcol = find_pos(w->w_line, w->w_char);		/* if the new dotcol is out of range, reselect		   a horizontal window */		if ((PhysScreen[i].s_offset == -1) ||		    (w->w_dotcol < strt_col) ||		    (w->w_dotcol >= end_col)) {			if (w->w_dotcol < ((CO - 2) - diff))				strt_col = 0;			else				strt_col = w->w_dotcol - (CO / 2);			if (ScrollAll) {				if (w->w_LRscroll != strt_col)					UpdModLine = YES;				w->w_LRscroll = strt_col;			}		}		w->w_dotline = i;		w->w_dotcol += diff;	}	des_p = &DesiredScreen[upper];	phys_p = &PhysScreen[upper];	for (i = upper, lp = w->w_top; lp != NULL && i < lower; i++, des_p++, phys_p++, lp = lp->l_next) {		des_p->s_window = w;		des_p->s_lp = lp;		/* ??? what is -(daddr)1?  Would NULL_DADDR work as well? -- DHR */		des_p->s_id = (lp == curline && DOLsave)?			-(daddr)1 : lp->l_dline & ~DIRTY;		des_p->s_flags = isdirty(lp) ? L_MOD : 0;		if (w->w_flags & W_NUMLINES)			des_p->s_vln = w->w_topnum + (i - upper);		else			des_p->s_vln = 0;		if (lp == w->w_line)			des_p->s_offset = strt_col;		else			des_p->s_offset = w->w_LRscroll;	}	/* Is structure assignment faster than copy each field separately? */	if (i < lower) {		static const struct scrimage	dirty_plate = { 0, DIRTY, 0, 0, 0, 0 },					clean_plate = { 0, 0, 0, 0, 0, 0 };		for (; i < lower; i++, des_p++, phys_p++)			if (phys_p->s_id != 0)				*des_p = dirty_plate;			else				*des_p = clean_plate;	}	des_p->s_window = w;	des_p->s_flags = 0;	/* ??? The following assignment is very questionable:	 * - it stores a pointer in an integer variable	 * - it counts on these values being distinct from	 *   disk addresses, 0 (NULL_DADDR), and -1.	 * -- DHR	 */	des_p->s_id = (daddr) w->w_bufp;	if (des_p->s_id != phys_p->s_id || UpdModLine)		des_p->s_flags = MODELINE | DIRTY;#ifdef	MAC	if (UpdModLine)		Modechange = YES;	if (w == curwind && w->w_control)		SetScrollBar(w->w_control);#endif}/* Write whatever is in mesgbuf (maybe we are Asking, or just printed   a message).  Turns off the UpdateMesg line flag. */voidDrawMesg(abortable)bool	abortable;{#ifndef	MAC		/* same reason as in redisplay() */	if (charp())		return;#endif	i_set(ILI, 0);	if (swrite(mesgbuf, NO, abortable)) {		cl_eol();		UpdMesg = NO;	}	flushscreen();}/* Goto the current position in the current window.  Presumably redisplay()   has already been called, and curwind->{w_dotline,w_dotcol} have been set   correctly. */private voidGotoDot(){	if (!InputPending) {		Placur(curwind->w_dotline,			curwind->w_dotcol - PhysScreen[curwind->w_dotline].s_offset);		flushscreen();	}}private intUntilEqual(start)register int	start;{	register struct scrimage	*des_p = &DesiredScreen[start],					*phys_p = &PhysScreen[start];	while ((start < ILI) && (des_p->s_id != phys_p->s_id)) {		des_p += 1;		phys_p += 1;		start += 1;	}	return start;}/* Calls the routine to do the physical changes, and changes PhysScreen to   reflect those changes. */private intAddLines(at, num)register int	at,		num;{	register int	i;	int	bottom = UntilEqual(at + num);	if (num == 0 || num >= ((bottom - 1) - at))		return NO;				/* we did nothing */	v_ins_line(num, at, bottom - 1);	/* Now change PhysScreen to account for the physical change. */	for (i = bottom - 1; i - num >= at; i--)		PhysScreen[i] = PhysScreen[i - num];	for (i = 0; i < num; i++)		PhysScreen[at + i].s_id = 0;	return YES;					/* we did something */}private intDelLines(at, num)register int	at,		num;{	register int	i;	int	bottom = UntilEqual(at + num);	if (num == 0 || num >= ((bottom - 1) - at))		return NO;	v_del_line(num, at, bottom - 1);	for (i = at; num + i < bottom; i++)		PhysScreen[i] = PhysScreen[num + i];	for (i = bottom - num; i < bottom; i++)		PhysScreen[i].s_id = 0;	return YES;}/* Update line linenum in window w.  Only set PhysScreen to DesiredScreen   if the swrite or cl_eol works, that is nothing is interupted by   characters typed. */private voidUpdLine(linenum)register int	linenum;{	register struct scrimage	*des_p = &DesiredScreen[linenum];	register Window	*w = des_p->s_window;	i_set(linenum, 0);	if (des_p->s_flags & MODELINE) {		ModeLine(w);	} else if (des_p->s_id) {		des_p->s_lp->l_dline &= ~DIRTY;		des_p->s_flags &= ~(DIRTY | L_MOD);#ifdef	ID_CHAR		if (UseIC) {			char	outbuf[MAXCOLS],				*lptr;			int	fromcol = (w->w_flags & W_NUMLINES) ? 8 : 0;			if (w->w_flags & W_NUMLINES)				swritef(outbuf, sizeof(outbuf), "%6d  ",					des_p->s_vln);			lptr = lcontents(des_p->s_lp);			DeTab(des_p->s_offset, lptr, outbuf + fromcol,				(sizeof outbuf) - 1 - fromcol,				des_p->s_window->w_flags & W_VISSPACE);			if (IDchar(outbuf, linenum, 0))				PhysScreen[linenum] = *des_p;			else if (i_set(linenum, 0), swrite(outbuf, NO, YES))				do_cl_eol(linenum);			else				PhysScreen[linenum].s_id = -1;		} else {#endif	/* ID_CHAR */			if (w->w_flags & W_NUMLINES)				(void) swrite(sprint("%6d  ", des_p->s_vln), NO, YES);			if (BufSwrite(linenum))				do_cl_eol(linenum);			else				PhysScreen[linenum].s_id = -1;#ifdef	ID_CHAR		}#endif	} else if (PhysScreen[linenum].s_id) {	/* not the same ... make sure */		do_cl_eol(linenum);	}}private voiddo_cl_eol(linenum)register int	linenum;{	cl_eol();	PhysScreen[linenum] = DesiredScreen[linenum];}#ifdef	ID_CHAR/* From here to the end of the file is code that tries to utilize the   insert/delete character feature on some terminals.  It is very confusing   and not so well written code, AND there is a lot of it.  You may want   to use the space for something else. */bool	IN_INSmode = FALSE;bool	UseIC = FALSE;int	IMlen;private int	DClen,	IClen,	MDClen,	MIClen,	CElen;voiddisp_opt_init(){	DClen = DC ? strlen(DC) : 0;	MDClen = M_DC ? strlen(M_DC) : 9999;	IClen = IC ? strlen(IC) : 0;	MIClen = M_IC ? strlen(M_IC) : 9999;	IMlen = IM ? strlen(IM) : 0;	CElen = CE ? strlen(CE) : 0;	UseIC = (IC || IM || M_IC);}voidINSmode(on)bool	on;{	if (on && !IN_INSmode) {		putpad(IM, 1);		IN_INSmode = YES;	} else if (!on && IN_INSmode) {		putpad(EI, 1);		IN_INSmode = NO;	}}private voidDeTab(s_offset, buf, outbuf, limit, visspace)int	s_offset;register char	*buf;char	*outbuf;size_t	limit;int	visspace;{	register char	*phys_p = outbuf,			c;	register int	pos = 0;	char		*limitp = &outbuf[limit];#define OkayOut(ch)	{ \	if ((pos++ >= s_offset) && (phys_p < limitp)) \		*phys_p++ = (ch); \}	while ((c = *buf++) != '\0') {		if (c == '\t') {			int	nchars = (tabstop - (pos % tabstop));			if (visspace) {				OkayOut('>');				nchars -= 1;			}			while (--nchars >= 0)				OkayOut(' ');		} else if (jiscntrl(c)) {			OkayOut('^');			OkayOut(c == 0177 ? '?' : c + '@');		} else {			if (visspace && c == ' ')				c = '_';			OkayOut(c);		}		if (pos - s_offset >= CO) {			phys_p = &outbuf[CO - 1];			*phys_p++ = '!';			break;		}	}	*phys_p = '\0';#undef	OkayOut}/* ID character routines full of special cases and other fun stuff like that.   It actually works though ...	Returns Non-Zero if you are finished (no differences left). */private boolIDchar(new, lineno, col)register char	*new;int	lineno,	col;{	register int	i;	int	j,		oldlen,		NumSaved;	register struct screenline	*sline = &Screen[lineno];	oldlen = sline->s_length - sline->s_line;	for (i = col; i < oldlen && new[i] != '\0'; i++)		if (sline->s_line[i] != new[i])			break;	if (new[i] == '\0' || i == oldlen)		return new[i] == '\0' && i == oldlen;	for (j = i + 1; j < oldlen && new[j]; j++) {		if (new[j] == sline->s_line[i]) {			NumSaved = IDcomp(new + j, sline->s_line + i,					(int)strlen(new)) + NumSimilar(new + i,						sline->s_line + i, j - i);			if (OkayInsert(NumSaved, j - i)) {				InsChar(lineno, i, j - i, new);				return IDchar(new, lineno, j);			}		}	}	for (j = i + 1; j < oldlen && new[i]; j++) {		if (new[i] == sline->s_line[j]) {			NumSaved = IDcomp(new + i, sline->s_line + j,					oldlen - j);			if (OkayDelete(NumSaved, j - i, new[oldlen] == '\0')) {				DelChar(lineno, i, j - i);				return IDchar(new, lineno, i);			}		}	}	return NO;}private intNumSimilar(s, t, n)register char	*s,		*t;int	n;{	register int	num = 0;	while (n--)		if (*s++ == *t++)			num += 1;	return num;}private intIDcomp(s, t, len)register char	*s,		*t;int	len;{

⌨️ 快捷键说明

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