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

📄 line.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1988 Mark Nudleman * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)line.c	8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * Routines to manipulate the "line buffer". * The line buffer holds a line of output as it is being built * in preparation for output to the screen. * We keep track of the PRINTABLE length of the line as it is being built. */#include <sys/types.h>#include <ctype.h>#include <less.h>static char linebuf[1024];	/* Buffer which holds the current output line */static char *curr;		/* Pointer into linebuf */static int column;		/* Printable length, accounting for				   backspaces, etc. *//* * A ridiculously complex state machine takes care of backspaces.  The * complexity arises from the attempt to deal with all cases, especially * involving long lines with underlining, boldfacing or whatever.  There * are still some cases which will break it. * * There are four states: *	LN_NORMAL is the normal state (not in underline mode). *	LN_UNDERLINE means we are in underline mode.  We expect to get *		either a sequence like "_\bX" or "X\b_" to continue *		underline mode, or anything else to end underline mode. *	LN_BOLDFACE means we are in boldface mode.  We expect to get sequences *		like "X\bX\b...X\bX" to continue boldface mode, or anything *		else to end boldface mode. *	LN_UL_X means we are one character after LN_UNDERLINE *		(we have gotten the '_' in "_\bX" or the 'X' in "X\b_"). *	LN_UL_XB means we are one character after LN_UL_X  *		(we have gotten the backspace in "_\bX" or "X\b_"; *		we expect one more ordinary character,  *		which will put us back in state LN_UNDERLINE). *	LN_BO_X means we are one character after LN_BOLDFACE *		(we have gotten the 'X' in "X\bX"). *	LN_BO_XB means we are one character after LN_BO_X *		(we have gotten the backspace in "X\bX"; *		we expect one more 'X' which will put us back *		in LN_BOLDFACE). */static int ln_state;		/* Currently in normal/underline/bold/etc mode? */#define	LN_NORMAL	0	/* Not in underline, boldface or whatever mode */#define	LN_UNDERLINE	1	/* In underline, need next char */#define	LN_UL_X		2	/* In underline, got char, need \b */#define	LN_UL_XB	3	/* In underline, got char & \b, need one more */#define	LN_BOLDFACE	4	/* In boldface, need next char */#define	LN_BO_X		5	/* In boldface, got char, need \b */#define	LN_BO_XB	6	/* In boldface, got char & \b, need same char */char *line;			/* Pointer to the current line.				   Usually points to linebuf. */extern int bs_mode;extern int tabstop;extern int bo_width, be_width;extern int ul_width, ue_width;extern int sc_width, sc_height;/* * Rewind the line buffer. */prewind(){	line = curr = linebuf;	ln_state = LN_NORMAL;	column = 0;}/* * Append a character to the line buffer. * Expand tabs into spaces, handle underlining, boldfacing, etc. * Returns 0 if ok, 1 if couldn't fit in buffer. */#define	NEW_COLUMN(addon) \	if (column + addon + (ln_state ? ue_width : 0) > sc_width) \		return(1); \	else \		column += addonpappend(c)	int c;{	if (c == '\0') {		/*		 * Terminate any special modes, if necessary.		 * Append a '\0' to the end of the line.		 */		switch (ln_state) {		case LN_UL_X:			curr[0] = curr[-1];			curr[-1] = UE_CHAR;			curr++;			break;		case LN_BO_X:			curr[0] = curr[-1];			curr[-1] = BE_CHAR;			curr++;			break;		case LN_UL_XB:		case LN_UNDERLINE:			*curr++ = UE_CHAR;			break;		case LN_BO_XB:		case LN_BOLDFACE:			*curr++ = BE_CHAR;			break;		}		ln_state = LN_NORMAL;		*curr = '\0';		return(0);	}	if (curr > linebuf + sizeof(linebuf) - 12)		/*		 * Almost out of room in the line buffer.		 * Don't take any chances.		 * {{ Linebuf is supposed to be big enough that this		 *    will never happen, but may need to be made 		 *    bigger for wide screens or lots of backspaces. }}		 */		return(1);	if (!bs_mode) {		/*		 * Advance the state machine.		 */		switch (ln_state) {		case LN_NORMAL:			if (curr <= linebuf + 1			    || curr[-1] != (char)('H' | 0200))				break;			column -= 2;			if (c == curr[-2])				goto enter_boldface;			if (c == '_' || curr[-2] == '_')				goto enter_underline;			curr -= 2;			break;enter_boldface:			/*			 * We have "X\bX" (including the current char).			 * Switch into boldface mode.			 */			column--;			if (column + bo_width + be_width + 1 >= sc_width)				/*				 * Not enough room left on the screen to 				 * enter and exit boldface mode.				 */				return (1);			if (bo_width > 0 && curr > linebuf + 2			    && curr[-3] == ' ') {				/*				 * Special case for magic cookie terminals:				 * if the previous char was a space, replace 				 * it with the "enter boldface" sequence.				 */				curr[-3] = BO_CHAR;				column += bo_width-1;			} else {				curr[-1] = curr[-2];				curr[-2] = BO_CHAR;				column += bo_width;				curr++;			}			goto ln_bo_xb_case;enter_underline:			/*			 * We have either "_\bX" or "X\b_" (including			 * the current char).  Switch into underline mode.			 */			column--;			if (column + ul_width + ue_width + 1 >= sc_width)				/*				 * Not enough room left on the screen to 				 * enter and exit underline mode.				 */				return (1);			if (ul_width > 0 && 			    curr > linebuf + 2 && curr[-3] == ' ')			{				/*				 * Special case for magic cookie terminals:				 * if the previous char was a space, replace 				 * it with the "enter underline" sequence.				 */				curr[-3] = UL_CHAR;				column += ul_width-1;			} else			{				curr[-1] = curr[-2];				curr[-2] = UL_CHAR;				column += ul_width;				curr++;			}			goto ln_ul_xb_case;			/*NOTREACHED*/		case LN_UL_XB:			/*			 * Termination of a sequence "_\bX" or "X\b_".			 */			if (c != '_' && curr[-2] != '_' && c == curr[-2])			{				/*				 * We seem to have run on from underlining				 * into boldfacing - this is a nasty fix, but				 * until this whole routine is rewritten as a				 * real DFA, ...  well ...				 */				curr[0] = curr[-2];				curr[-2] = UE_CHAR;				curr[-1] = BO_CHAR;				curr += 2; /* char & non-existent backspace */				ln_state = LN_BO_XB;				goto ln_bo_xb_case;			}ln_ul_xb_case:			if (c == '_')				c = curr[-2];			curr -= 2;			ln_state = LN_UNDERLINE;			break;		case LN_BO_XB:			/*			 * Termination of a sequnce "X\bX".			 */			if (c != curr[-2] && (c == '_' || curr[-2] == '_'))			{				/*				 * We seem to have run on from				 * boldfacing into underlining.				 */				curr[0] = curr[-2];				curr[-2] = BE_CHAR;				curr[-1] = UL_CHAR;				curr += 2; /* char & non-existent backspace */				ln_state = LN_UL_XB;				goto ln_ul_xb_case;			}ln_bo_xb_case:			curr -= 2;			ln_state = LN_BOLDFACE;			break;		case LN_UNDERLINE:			if (column + ue_width + bo_width + 1 + be_width >= sc_width)				/*				 * We have just barely enough room to 				 * exit underline mode and handle a possible				 * underline/boldface run on mixup.				 */				return (1);			ln_state = LN_UL_X;			break;		case LN_BOLDFACE:			if (c == '\b')			{				ln_state = LN_BO_XB;				break;			}			if (column + be_width + ul_width + 1 + ue_width >= sc_width)				/*				 * We have just barely enough room to 				 * exit underline mode and handle a possible				 * underline/boldface run on mixup.				 */				return (1);			ln_state = LN_BO_X;			break;		case LN_UL_X:			if (c == '\b')				ln_state = LN_UL_XB;			else			{				/*				 * Exit underline mode.				 * We have to shuffle the chars a bit				 * to make this work.				 */				curr[0] = curr[-1];				curr[-1] = UE_CHAR;				column += ue_width;				if (ue_width > 0 && curr[0] == ' ')					/*					 * Another special case for magic					 * cookie terminals: if the next					 * char is a space, replace it					 * with the "exit underline" sequence.					 */					column--;				else					curr++;				ln_state = LN_NORMAL;			} 			break;		case LN_BO_X:			if (c == '\b')				ln_state = LN_BO_XB;			else			{				/*				 * Exit boldface mode.				 * We have to shuffle the chars a bit				 * to make this work.				 */				curr[0] = curr[-1];				curr[-1] = BE_CHAR;				column += be_width;				if (be_width > 0 && curr[0] == ' ')					/*					 * Another special case for magic					 * cookie terminals: if the next					 * char is a space, replace it					 * with the "exit boldface" sequence.					 */					column--;				else					curr++;				ln_state = LN_NORMAL;			} 			break;		}	}	if (c == '\t') {		/*		 * Expand a tab into spaces.		 */		do {			NEW_COLUMN(1);		} while ((column % tabstop) != 0);		*curr++ = '\t';		return (0);	}	if (c == '\b') {		if (ln_state == LN_NORMAL)			NEW_COLUMN(2);		else			column--;		*curr++ = ('H' | 0200);		return(0);	} 	if (CONTROL_CHAR(c)) {		/*		 * Put a "^X" into the buffer.  The 0200 bit is used to tell		 * put_line() to prefix the char with a ^.  We don't actually		 * put the ^ in the buffer because we sometimes need to move		 * chars around, and such movement might separate the ^ from		 * its following character.		 */		NEW_COLUMN(2);		*curr++ = (CARAT_CHAR(c) | 0200);		return(0);	}	/*	 * Ordinary character.  Just put it in the buffer.	 */	NEW_COLUMN(1);	*curr++ = c;	return (0);}/* * Analogous to forw_line(), but deals with "raw lines": * lines which are not split for screen width. * {{ This is supposed to be more efficient than forw_line(). }} */off_tforw_raw_line(curr_pos)	off_t curr_pos;{	register char *p;	register int c;	off_t new_pos, ch_tell();	if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||		(c = ch_forw_get()) == EOI)		return (NULL_POSITION);	p = linebuf;	for (;;)	{		if (c == '\n' || c == EOI)		{			new_pos = ch_tell();			break;		}		if (p >= &linebuf[sizeof(linebuf)-1])		{			/*			 * Overflowed the input buffer.			 * Pretend the line ended here.			 * {{ The line buffer is supposed to be big			 *    enough that this never happens. }}			 */			new_pos = ch_tell() - 1;			break;		}		*p++ = c;		c = ch_forw_get();	}	*p = '\0';	line = linebuf;	return (new_pos);}/* * Analogous to back_line(), but deals with "raw lines". * {{ This is supposed to be more efficient than back_line(). }} */off_tback_raw_line(curr_pos)	off_t curr_pos;{	register char *p;	register int c;	off_t new_pos, ch_tell();	if (curr_pos == NULL_POSITION || curr_pos <= (off_t)0 ||		ch_seek(curr_pos-1))		return (NULL_POSITION);	p = &linebuf[sizeof(linebuf)];	*--p = '\0';	for (;;)	{		c = ch_back_get();		if (c == '\n')		{			/*			 * This is the newline ending the previous line.			 * We have hit the beginning of the line.			 */			new_pos = ch_tell() + 1;			break;		}		if (c == EOI)		{			/*			 * We have hit the beginning of the file.			 * This must be the first line in the file.			 * This must, of course, be the beginning of the line.			 */			new_pos = (off_t)0;			break;		}		if (p <= linebuf)		{			/*			 * Overflowed the input buffer.			 * Pretend the line ended here.			 */			new_pos = ch_tell() + 1;			break;		}		*--p = c;	}	line = p;	return (new_pos);}

⌨️ 快捷键说明

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