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

📄 ei_plain_text.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lint#ifdef sccsstatic  char sccsid[] = "@(#)ei_plain_text.c 1.1 92/07/30";#endif#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Entity interpreter for ascii characters interpreted as plain text. */#define USING_SETS#include <suntool/primal.h>#include <sys/time.h>#include <stdio.h>#include <ctype.h>#include <pixrect/pixrect.h>#include <pixrect/pr_util.h>#include <pixrect/memvar.h>#include <pixrect/pixfont.h>#include <sunwindow/rect.h>#undef max#include <sunwindow/rectlist.h>#include <sunwindow/pixwin.h>#include <suntool/tool.h>#include <suntool/entity_view.h>extern Es_index		es_backup_buf();extern void		pw_batch();		/* Used by pw_batch_on/off */#define	NEWLINE	'\n'#define	SPACE	' '#define	TAB	'\t'typedef struct ei_plain_text_object {	PIXFONT		*font;	int		 tab_width;	/* tab width in 'm's */	unsigned	 state;	struct pr_pos	 font_home;	/* == fonthome(font) */	int		 font_flags;	short		 tab_pixels;	/* tab width in pixels */	short		 tab_delta_y;	/* actually ' ' delta y */} ei_plain_text_object;typedef ei_plain_text_object *Eipt_handle;#define	ABS_TO_REP(eih)	(Eipt_handle)LINT_CAST(eih->data)/* * Note: font_home, font_flags, tab_pixels, and tab_delta_y are *	 cached information which must be updated when the font *	 or the tab_width change. */	/* state values */#define CONTROL_CHARS_USE_FONT	0x0000001	/* font_flags values */#define FF_POSITIVE_X_ADVANCE	0x0000001#define FF_UNIFORM_HEIGHT	0x0000002#define FF_UNIFORM_HOME		0x0000004#define FF_UNIFORM_X_ADVANCE	0x0000008#define FF_UNIFORM_X_PR_ADVANCE	0x0000010#define FF_ZERO_Y_ADVANCE	0x0000020#define	FF_ALL			0x000003f#define FF_EASY_Y		(FF_UNIFORM_HEIGHT|FF_UNIFORM_HOME| \				 FF_ZERO_Y_ADVANCE)extern Ei_handle			ei_plain_text_create();static Ei_handle			ei_plain_text_destroy();static caddr_t				ei_plain_text_get();static int				ei_plain_text_line_height();static int				ei_plain_text_lines_in_rect();static struct ei_process_result		ei_plain_text_process();static int				ei_plain_text_set();static struct ei_span_result		ei_plain_text_span_of_group();static struct ei_process_result		ei_plain_text_expand();struct ei_ops ei_plain_text_ops  =  {	ei_plain_text_destroy,	ei_plain_text_get,	ei_plain_text_line_height,	ei_plain_text_lines_in_rect,	ei_plain_text_process,	ei_plain_text_set,	ei_plain_text_span_of_group,	ei_plain_text_expand};/* Used in ei_plain_text_process. Init adv.y = 0 once and for all. */static struct pixchar			 dummy_for_tab;static intei_plain_text_set_tab_width(eih, tab_width)	Ei_handle	eih;	register int	tab_width;{	register Eipt_handle	 private = ABS_TO_REP(eih);	private->tab_width = tab_width;	private->tab_pixels =	    private->font->pf_char['m'].pc_adv.x * tab_width;	if (private->tab_pixels == 0)	    private->tab_pixels = 1;}static intei_plain_text_set_font(eih, font)	Ei_handle		 eih;	register PIXFONT	*font;{	extern struct pr_pos	 fonthome();	register Eipt_handle	 private = ABS_TO_REP(eih);	struct pixchar		*pc = &font->pf_char[SPACE];	register short		 i, height, home, adv_x;	private->font = font;	private->font_home = fonthome(font);	ei_plain_text_set_tab_width(eih, private->tab_width);	height = pc->pc_pr->pr_height;	home = pc->pc_home.y;	private->tab_delta_y = home + height;	adv_x = pc->pc_adv.x;	/* Assume that this is >= 0 */	private->font_flags = FF_ALL;	for (i = 0; i < 256; i++) {	    pc = &font->pf_char[i];	    if (adv_x != pc->pc_adv.x) {		if (pc->pc_pr) {		    private->font_flags &=			~(FF_UNIFORM_X_ADVANCE|FF_UNIFORM_X_PR_ADVANCE);		} else {		    private->font_flags &= ~FF_UNIFORM_X_ADVANCE;		}		if (adv_x < 0) {		    private->font_flags &= ~FF_POSITIVE_X_ADVANCE;		}	    }	    if (pc->pc_adv.y != 0) {		private->font_flags &= ~FF_ZERO_Y_ADVANCE;	    }	    if (pc->pc_pr) {		/* Home is meaningless unless pixrect exists for char. */		if (home != pc->pc_home.y) {		    private->font_flags &= ~FF_UNIFORM_HOME;		}		if (height != pc->pc_pr->pr_height) {		    private->font_flags &= ~FF_UNIFORM_HEIGHT;		}	    }	}#ifdef DEBUG	(void) fprintf(stderr, "Font_flags: %lx\n", private->font_flags);#endif}extern Ei_handleei_plain_text_create(){	extern char		*calloc();	register Ei_handle	 eih = NEW(struct ei_object);	Eipt_handle		 private;	if (eih == 0)	    goto AllocFailed;	private = NEW(ei_plain_text_object);	if (private == 0)  {	    free((char *)eih);	    goto AllocFailed;	}	eih->ops = &ei_plain_text_ops;	eih->data = (caddr_t)private;	private->tab_width = 8;	return(eih);AllocFailed:	return(NULL);}static Ei_handleei_plain_text_destroy(eih)	Ei_handle eih;{	register Eipt_handle private = ABS_TO_REP(eih);	free((char *)eih);	free((char *)private);	return NULL;}static intei_plain_text_line_height(eih)	Ei_handle	 eih;{	register Eipt_handle private = ABS_TO_REP(eih);	return(private->font->pf_defaultsize.y);}static intei_plain_text_lines_in_rect(eih, rect)	Ei_handle	 eih;	struct rect	*rect;/* * Returns the number of complete lines that will fit in the rect. * Any partial line is ignored; call with one bit shorter rect to check *   if partial exists. */{	register int	line_height = ei_line_height(eih);	int		result = rect->r_height/line_height;	return(result < 0 ? 0 : result);}static u_short  gray17_data[16] = {	/*	really 16-2/3	*/        0x8208, 0x2082, 0x0410, 0x1041, 0x4104, 0x0820, 0x8208, 0x2082,        0x0410, 0x1041, 0x4104, 0x0820, 0x8208, 0x2082, 0x0410, 0x1041};mpr_static(gray17_pr, 12, 12, 1, gray17_data);/* The following macros (suggested by JAG) make sure the compiler keeps * all the involved quantities as short's. */#define	SAdd(_a, _b)	(short)((short)(_a) + (short)(_b))#define	SSub(_a, _b)	(short)((short)(_a) - (short)(_b))#define	SRect_edge(_a, _b)	\			(short)((short)((short)(_a) + (short)(_b)) - (short)1)#define MAX_PER_BATCH 200static struct ei_process_resultei_plain_text_process(eih, op, esbuf, x, y, rop, pw, rect, tab_origin)	Ei_handle		 eih;	int			 op;	Es_buf_handle		 esbuf;	int			 x, y, rop;	struct pixwin		*pw;	register struct rect	*rect;	int			 tab_origin;/* * Arguments are: *   eih	handle of the entity interpreter whose ei_process op *		mapped to this routine. *   op		see EI_OP_* in entity_interpreter.h. *   esbuf	chars to be painted/measured. *	sizeof_buf	number of characters in buffer. *	buf		the characters themselves. *	esh		handle of entity stream they came from. *	first		Es_index into esh. *	last_plus_one	Es_index into esh. *   x		position to start painting from. *   y		position of the largest ascender's top, NOT the baseline. *		Probably always == rect.r_top. *   rop	raster op, usually either PIX_SRC or PIX_SRC|PIX_DST. *   pw		pixwin to paint into. *   rect	rectangle to paint into, indicates where to stop with *		result.break_reason = EI_HIT_RIGHT, or whether to do *		nothing due to result.break_reason = EI_HIT_BOTTOM. *		r_left only needs to be different from x if we are *		starting to paint later than the beginning of the line, *		and op specifies EI_OP_CLEAR_FRONT. *   tab_origin	x position of zeroth tab stop on the line. * *   WARNING!  This code has been extensively hand tuned to make sure that * the compiler generates good code.  Seemingly trivial changes can impact * the generated code.  If you change this code, make sure you look at the * actual assembly code both before and after. */{	register Eipt_handle		 private = ABS_TO_REP(eih);	register struct pixchar		*pc;	register struct pr_prpos	*batch;	register short			 c;	register short			 temp;	register Es_index		 esi;	char				*buf_rep = (char *)esbuf->buf;	struct ei_process_result	 result;	short				 last_batch_pos_x, last_batch_pos_y;	register short			 bounds_right, rects_right;	short				 bounds_bottom, rects_bottom;	short				 in_white_space = 0, special_char = -1;	register int			 check_vert_bounds = TRUE;	struct pr_prpos			 prpos;	struct pr_prpos			 batch_array[MAX_PER_BATCH+1];	temp = (short)x;	last_batch_pos_x = temp;	result.bounds.r_left = temp;	bounds_right = temp;	result.pos.x = SSub(temp, private->font_home.x);	result.bounds.r_width = 0;	temp = (short)y;	last_batch_pos_y = temp;	result.bounds.r_top = temp;	/* BUG ALERT! The following is not completely correct, as it assumes	 *	that the result.bounds.r_top is at the top of the current	 *	line, not just the current "ink" for the batch.	 *   Make sure that clear|invert|pattern in paint_batch affects	 * the entire height of the line.	 */	bounds_bottom = SSub(SAdd(temp, private->font->pf_defaultsize.y), 1);	result.pos.y = SSub(temp, private->font_home.y);	rects_right = SRect_edge(rect->r_left, rect->r_width);	rects_bottom = SRect_edge(rect->r_top, rect->r_height);	result.break_reason = EI_PR_BUF_EMPTIED;	/*	 * Construct the batch items for the characters to be displayed.	 * During the batch construction, result.pos accumulates the advances	 *   along the baseline, and is an absolute position.	 * After building the batch, it is offset by font_home, thereby being	 *   the accumulation of the advances applied to the original x,y args.	 * last_batch_pos_x&y is absolute home position of the previous batch	 *   item.	 * Remember that batch->pos is a relative offset from previous item.	 */	batch = batch_array;	for (esi=esbuf->first; esi<esbuf->last_plus_one; esi++) {	    c = (unsigned char)(*buf_rep++);Rescan:	    if ((c == SPACE) || (c == TAB)) {		if (in_white_space == 0)		    in_white_space = 1;		if (c == TAB) {		    pc = &dummy_for_tab;		    /* dummy_for_tab.pc_adv.y = 0 implicitly due		     * to declaring dummy_for_tab as a static.		     */		    pc->pc_pr = 0;		    /* Don't set pc->pc_home as it is never examined */		    pc->pc_adv.x = (result.pos.x-tab_origin) %					private->tab_pixels;		    pc->pc_adv.x = private->tab_pixels - pc->pc_adv.x;		    /* Must explicitly test right boundary hit */		    temp = (short)pc->pc_adv.x - (short)1;		    temp += result.pos.x;		    if (temp > bounds_right) {			if (temp > rects_right) {			    result.break_reason = EI_PR_HIT_RIGHT;			    break;			}			bounds_right = temp;		    }		    /* ... and bottom */		    if (check_vert_bounds) {			temp = (short)private->tab_delta_y;			temp += result.pos.y;			if (--temp > bounds_bottom) {			    if (temp > rects_bottom) {				result.break_reason = EI_PR_HIT_BOTTOM;				break;			    }			    bounds_bottom = ++temp;			}			if (private->font_flags & FF_EASY_Y)			    check_vert_bounds = FALSE;		    }		    goto Skip_pc_pr_tests;		}	    } else if (c == NEWLINE) {		in_white_space = 0;		pc = &private->font->pf_char[SPACE];		goto Skip_pc_assignment;	    } else {		in_white_space = 0;	    }	    pc = &private->font->pf_char[c];Skip_pc_assignment:	    if (pc->pc_pr &&		(!iscntrl(c) || in_white_space || c == NEWLINE ||		(private->state & CONTROL_CHARS_USE_FONT))) {		batch->pr = pc->pc_pr;		temp = (short)pc->pc_home.x;		temp += result.pos.x;		if (temp < result.bounds.r_left) {		    if (temp < rect->r_left) {			result.break_reason = EI_PR_HIT_LEFT;			break;		    }		    result.bounds.r_left = temp;		}		batch->pos.x = SSub(temp, last_batch_pos_x);		last_batch_pos_x = temp;		temp += pc->pc_pr->pr_width - 1;		if (temp > bounds_right) {		    if (temp > rects_right) {			result.break_reason = EI_PR_HIT_RIGHT;			if (special_char < -1) {			    batch--;			    result.bounds.r_width = -2-special_char;			}			break;		    }		    bounds_right = temp;		}		if (check_vert_bounds) {		    temp = (short)pc->pc_home.y;		    temp += result.pos.y;		    if (temp < result.bounds.r_top) {			if (temp < rect->r_top) {			    result.break_reason = EI_PR_HIT_TOP;			    break;			}			result.bounds.r_top = temp;		    }		    batch->pos.y = SSub(temp, last_batch_pos_y);		    last_batch_pos_y = temp;		    temp += pc->pc_pr->pr_height - 1;		    if (temp > bounds_bottom) {			if (temp > rects_bottom) {			    result.break_reason = EI_PR_HIT_BOTTOM;			    break;			}			bounds_bottom = temp;		    }		    if (private->font_flags & FF_EASY_Y)			check_vert_bounds = FALSE;		} else {		    batch->pos.y = 0;		}		batch++;	    } else {		special_char = (c < ' ') ? c+64 : '?';		c = '^';		goto Rescan;	    }Skip_pc_pr_tests:	    /* Accumulate advances for caller and ourselves. */	    result.pos.x += pc->pc_adv.x;	    result.pos.y += pc->pc_adv.y;	    if (special_char != -1) {		if (special_char >= 0) {		    c = special_char;		    special_char = -2-result.bounds.r_width;		    goto Rescan;		} else special_char = -1;	    }	    if (c == NEWLINE) break;	}	if (c == NEWLINE)		/* Note following overrides possible EI_PR_HIT_RIGHT above. */		result.break_reason = EI_PR_NEWLINE;	result.last_plus_one = esi;	result.bounds.r_width = bounds_right - result.bounds.r_left + 1;	result.bounds.r_height = bounds_bottom - result.bounds.r_top + 1;	result.considered = esi;	if (op & EI_OP_MEASURE) {	} else {	    int	batch_length = batch - batch_array;					/* C does "/ sizeof(struct)" */	    paint_batch(op, x, y, rop, pw, rect, prpos,			batch_array, batch_length, &result.bounds);	}	result.pos.x += private->font_home.x;	result.pos.y += private->font_home.y;	return(result);}staticpaint_batch(op, x, y, rop, pw, rect, prpos, batch, batch_length, bounds)	register int		 op, x, y, rop;	register struct pixwin	*pw;	register struct rect	*rect;	struct pr_prpos		 prpos,				*batch;	int			 batch_length;	register struct rect	*bounds;{#define EI_OP_CLEAR_ALL EI_OP_CLEAR_FRONT|EI_OP_CLEAR_INTERIOR|EI_OP_CLEAR_BACK	register int		 temp;	/* Write to memory image, if retained */	pw_batch_on(pw);	if (op & EI_OP_CLEAR_ALL) {#define bounds_right	temp	    bounds_right = bounds->r_left + bounds->r_width;	    if ((op & EI_OP_CLEAR_ALL) == EI_OP_CLEAR_INTERIOR) {		(void) pw_lock(pw, bounds);	    } else {		struct rect	extend_bounds;		extend_bounds.r_left = rect->r_left;		extend_bounds.r_top = bounds->r_top;		extend_bounds.r_width = rect->r_width;		extend_bounds.r_height = bounds->r_height;		(void) pw_lock(pw, &extend_bounds);	    }	    if (op & EI_OP_CLEAR_FRONT)		(void) pw_write(pw,

⌨️ 快捷键说明

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