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

📄 pf.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
#ifdef sccs#ifndef lintstatic char sccsid[] = "@(#)pf.c 1.1 92/07/30 SMI from pf.c 1.20 87/12/18";#endif#endif/* * Copyright 1986-1989 Sun Microsystems, Inc. *//* * Pixfont open/close: pf_open(), pf_open_private(), pf_close() */#include <vfont.h>#include <stdio.h>#include <strings.h>#include <sys/types.h>#include <pixrect/pixrect.h>#include <pixrect/pixfont.h>#include <pixrect/memvar.h>#include <pixrect/pr_impl_util.h>#ifndef MP_FONT	/* in case we have the wrong memvar.h */#define	MP_FONT		32	/* Pixrect is a part of a Pixfont */#endif#ifndef	NO_SHARED_LIB_FONTS#include <errno.h>#include <fcntl.h>#include <sys/mman.h>#include <link.h>extern int			errno;extern struct link_dynamic	_DYNAMIC;extern int			getpagesize();extern char			*getenv();#endifextern char *calloc(), *malloc();extern Pixfont *pf_resident(), *pf_bltindef();static Pixfont *pf_load_vfont();#ifndef	NO_SHARED_LIB_FONTS/*	Following added to allow a master program (e.g. sunview) * to change allocation for fonts to force them into particular VM addresses * so that slave programs (e.g. shelltool) can try to share the same fonts. * This only works if both master and slave are linked against the same set * of shared libraries with the same initial stack sizes (the common case), * but mem_ops fields exist to allow this condition to be checked. *	_use_vm has the following meanings (assuming pf_linked_dynamic() is * true, otherwise we have to use private fonts): * 0: slave, try to get font from vm * 1: master, try to put font into vm * 2: either, vm did not work, don't try it any longer. */static	int _use_vm; static	int vm_fd;		/* Only valid while master loading fonts */static	char *next_free, *end_of_vm_blk;typedef	struct pixrectops Pr_ops;#define PF_VM_VERSION	1#define MAX_FONT_COUNT	4typedef struct pf_vm_header {	int		 version;	 /* Should be PF_VM_VERSION */	caddr_t		 mapped_at;	 /* Assigned VM addr. */	int		 size_of_vm_blk; /* In bytes, including header */	Pr_ops		*mem_ops;	 /* Must match or don't share */	Pr_ops		 mem_ops_procs;  /*   fonts as VM layout bad */	int		 font_count;	 /* No. of valid fonts */	Pixfont		*fonts[MAX_FONT_COUNT];	char		 font_names[MAX_FONT_COUNT][1024];	int		 vm_blk[1];	 /* Lie: actually much bigger */} *Pf_vm_header;static	Pf_vm_header vm_header;#define	VM_FONT_FILE	"/usr/tmp/vm_fonts-"#endif/* shared font list */static struct font_use {	struct font_use *next;	char *name;	Pixfont *pf;	int count;	int resident;} Fonts[1];/* public functions */#ifndef NO_SHARED_LIB_FONTSintpf_linked_dynamic(){	return (&_DYNAMIC != (struct link_dynamic *)0);}intpf_use_vm(use_vm)	int	use_vm;{	int	result = _use_vm;	/* Make sure that we actually got built with shared libraries */	if (pf_linked_dynamic()) {		if (_use_vm == 1 && use_vm == 0 && vm_fd > 0) {			/*			 * Turning off vm => close backing file.			 * Change permissions to make it read only for others.			 * (We still retain write access.)			 */			if (fchmod(vm_fd, 0444) < 0) {				perror("fchmod");			}			close(vm_fd);			vm_fd = 0;		}		_use_vm = use_vm ? 1 : 0;	}	return result;}#endifPixfont *pf_open(fontname)	char *fontname;{	register struct font_use *use, *prev;	register char *basename;#ifndef NO_SHARED_LIB_FONTS	int		from_vm;#endif	if (fontname == 0) 		return pf_default();	if (basename = rindex(fontname, '/'))		basename++;	else		basename = fontname;	/* look for the font in the shared font list */	for (prev = Fonts; use = prev->next; prev = use) 		if (strcmp(use->name, basename) == 0) {			/* found it */			use->count++;			return use->pf;		}	/* didn't find it, add it to the end of the list */	if (use = (struct font_use *) 		malloc((unsigned) (sizeof *use + strlen(basename) + 1))) {		use->next = 0;		(void) strcpy(use->name = (char *) (use + 1), basename);		use->count = 1;		use->resident = 0;		if (use->pf = pf_resident(basename))			use->resident = 1;		else {#ifndef NO_SHARED_LIB_FONTS			use->pf = pf_load_vfont(fontname, &from_vm);			use->resident = from_vm;#else			use->pf = pf_load_vfont(fontname);#endif		}		if (use->pf) {			prev->next = use;			return use->pf;		}		else			(void) free((char *) use);	}	return 0;}Pixfont *pf_open_private(fontname)	char *fontname;{#ifndef NO_SHARED_LIB_FONTS	/* Set allocator to calloc() to force private copy of font. */	int		save_use_vm = _use_vm;	int		from_vm;#endif	Pixfont		*result;	/* 	 * We don't know the name of the default font, and	 * there is no code to copy it, so we punt.	 */	if (fontname == 0)		return 0;#ifndef NO_SHARED_LIB_FONTS	_use_vm = 2;	result = pf_load_vfont(fontname, &from_vm);	_use_vm = save_use_vm;#else	result = pf_load_vfont(fontname);#endif	return result;}pf_close(pf)	Pixfont *pf;{	register struct font_use *use, *prev;	if (pf == 0 || pf == pf_bltindef())		return 0;	/* look for a font in the shared font list */	for (prev = Fonts; use = prev->next; prev = use) {		if (use->pf == pf) {			/* found it */			if (--use->count <= 0) {				if (!use->resident)					free((char *) pf);				prev->next = use->next;				(void) free((char *) use);			}			return 0;		}	}	/* didn't find font, must be private */	free((char *) pf);	return 0;}/* implementation */#ifndef	NO_SHARED_LIB_FONTS/* Following routine computes the file name of the vm backing storage. * It will try to use the information in the WINDOW_PARENT environment * variable to generate names unique for a desktop, so that users with * multiple monitors can run multiple sunviews without getting collisions. */static voidpf_vm_font_file(buf)	char	*buf;/* Caller must provide a buf that is at least 1024 chars long. */{	char	*window_parent = getenv("WINDOW_PARENT");	strcpy(buf, VM_FONT_FILE);	if (window_parent != NULL && window_parent[0] != '\0') {		strcat(buf, &window_parent[strlen(window_parent)-2]);	}}static char *pf_alloc_vm(to_alloc)	int	 to_alloc;/* Caller must have rounded to_alloc to page boundary, and should only * call if pf_linked_dynamic() is true. */{	register struct link_map	*lmp;	int				retried = 0;	char				vm_file_name[1024];	caddr_t				mappedat;	/*	 * Map in the file and set its length long enough to hold	 * the mapped region.	 */	pf_vm_font_file(vm_file_name);Open:	if ((vm_fd = open(vm_file_name,			  O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0) {		if (errno == EACCES && !retried) {			/* Assume left over from prior master and remove. */			if (unlink(vm_file_name) == 0) {				retried = 1;				goto Open;			}		}		perror("open");		goto Error_return;	}	if (ftruncate(vm_fd, to_alloc) < 0) {		perror("ftruncate");		goto Error_return;	}	mappedat = mmap(0, to_alloc, PROT_WRITE | PROT_READ,			MAP_SHARED, vm_fd, (off_t) 0);	if (mappedat == (caddr_t) -1) {		perror("mmap");		goto Error_return;	}	return(mappedat);Error_return:	if (vm_fd) {		close(vm_fd);		vm_fd = 0;	}	return(0);}static Pf_vm_headerpf_map_vm()/* Caller should only call if pf_linked_dynamic() is true. */{	struct pf_vm_header	vm_header;	register int		fd, len, page_size;	char			mincore_status, vm_file_name[1024];	register caddr_t	mapped_at;	/*	 * Get a handle on the file to be mapped in, and read the header.	 */	pf_vm_font_file(vm_file_name);	if ((fd = open(vm_file_name, O_RDONLY)) < 0) {		if (errno != ENOENT) {			perror("open");		}		goto Error_return;	}	len = read(fd, &vm_header, sizeof(vm_header));	if (len != sizeof(vm_header)) {		perror("read");		goto Error_return;	}	page_size = getpagesize();	if (vm_header.version != PF_VM_VERSION ||	    ((int)(vm_header.mapped_at) % page_size) != 0 ||	    vm_header.size_of_vm_blk > 1024000) {		/* Header looks bad: punt. */		goto Error_return;	}	/*	 * Check to see if all of specified block is unmapped.	 * If so, attempt to map file at the specified address.	 */	for (len = vm_header.size_of_vm_blk, mapped_at = vm_header.mapped_at;	     len > 0; len -= page_size, mapped_at += page_size) {		if (mincore(mapped_at, page_size, &mincore_status) != -1 ||		    errno != ENOMEM) {			/* Block of memory is partially mapped: punt. */			goto Error_return;		}	}	mapped_at = mmap(vm_header.mapped_at, vm_header.size_of_vm_blk,			PROT_READ, MAP_SHARED | MAP_FIXED, fd, (off_t) 0);	if (mapped_at == (caddr_t) -1) {		perror("mmap");		goto Error_return;	}	close(fd);	/* fd not needed after mmap completes. */	return (Pf_vm_header)mapped_at;Error_return:	if (fd >= 0) {		close(fd);	}	return (Pf_vm_header)0;}static Pixfont *pf_alloc_font(fontname, size, from_vm)	register char		*fontname;	register int		*from_vm;{	register Pixfont	*pf;	register int		 to_alloc;	register int		 page_size;	if (!pf_linked_dynamic() || (_use_vm != 1)) {		goto No_vm;	}	/* Defining fonts (master) : place in VM */	if (next_free == (char *)0) {		/* Allocate in pages, and guess a little high in case		 * the first font is a small font and to allow some		 * room for the vm_header itself.		 */		page_size = getpagesize();		to_alloc = (2+MAX_FONT_COUNT) * size;		to_alloc = ((to_alloc+page_size-1)/page_size) *			   page_size;		next_free = pf_alloc_vm(to_alloc);		if (next_free == (char *)0) {			_use_vm = 0;			goto No_vm;		}		end_of_vm_blk = next_free + to_alloc;		vm_header = (Pf_vm_header)next_free;		vm_header->version = PF_VM_VERSION;		vm_header->mapped_at = (caddr_t)vm_header;		vm_header->size_of_vm_blk = to_alloc;		vm_header->mem_ops = &mem_ops;		bcopy((char *)&mem_ops,		      (char *)&(vm_header->mem_ops_procs),		      sizeof(mem_ops));		vm_header->font_count = 0;		next_free = (char *)vm_header->vm_blk;	}	if (vm_header->font_count == MAX_FONT_COUNT ||	    next_free+size >= end_of_vm_blk) {		goto No_vm;	}	pf = (Pixfont *)next_free;	*from_vm = 1;	/* Always align to next int boundary */	next_free += ((size+sizeof(int)-1)/sizeof(int)) * sizeof(int);	/* Remember this font */	strcpy(vm_header->font_names[vm_header->font_count], fontname);	vm_header->fonts[vm_header->font_count] = pf;	vm_header->font_count++;	return pf;No_vm:	*from_vm = 0;	pf = (Pixfont *)calloc(1, size);	return pf;}#endifstatic Pixfont *#ifndef	NO_SHARED_LIB_FONTSpf_load_vfont(fontname, from_vm)	char *fontname;	int  *from_vm;#elsepf_load_vfont(fontname)	char *fontname;#endif{	FILE *fontf;	struct header hd;	int defx, defy;	register struct dispatch *d;	register unsigned nfont, nimage;	register Pixfont *pf = 0;	struct dispatch disp[NUM_DISPATCH];#ifndef	NO_SHARED_LIB_FONTS	int	i;	/* Try looking in VM iff a slave. */	if (pf_linked_dynamic() && (_use_vm == 0)) {		if (vm_header == (Pf_vm_header)0) {			vm_header = pf_map_vm();			if (vm_header == (Pf_vm_header)0	||			    vm_header->mem_ops != &mem_ops	||			    bcmp((char *)&mem_ops,				 (char *)&(vm_header->mem_ops_procs),				 sizeof(mem_ops)) != 0	) {				_use_vm = 2;				goto No_vm;			}		}		for (i = 0; i < vm_header->font_count; i++) {			if (0 == strcmp(fontname, vm_header->font_names[i])) {				pf = vm_header->fonts[i];				*from_vm = 1;				return pf;			}		}	}No_vm:#endif	if (!(fontf = fopen(fontname, "r")))		return pf;	if (fread((char *) &hd, sizeof hd, 1, fontf) != 1 ||		fread((char *) disp, sizeof disp, 1, fontf) != 1 ||		hd.magic != VFONT_MAGIC)		goto bad;	/* 	 * Set default sizes.  The default width of the font is taken to be	 * the width of a lower-case a, if there is one. The default	 * interline spacing is taken to be 3/2 the height of an	 * upper-case A above the baseline.	 */	if (disp['a'].nbytes && disp['a'].width > 0 &&		disp['A'].nbytes && disp['A'].up > 0) {		defx = disp['a'].width;		defy = disp['A'].up * 3 >> 1;	}	else {		defx = hd.maxx;		defy = hd.maxy + hd.xtend;	}	if (defx <= 0 || defy <= 0)		goto bad;	/* compute total font and image size */	nfont = sizeof (struct pixfont);	nimage = 0;	for (d = disp; d < &disp[NUM_DISPATCH]; d++)		if (d->nbytes) {			register int w, h;			if ((w = d->left + d->right) <= 0 ||				(h = d->up + d->down) <= 0) {				d->nbytes = 0;				continue;			}			nfont += sizeof (struct pixrect) +				sizeof (struct mpr_data);			w = w <= 16 ? 2 : w + 31 >> 5 << 2;			/* may need extra space to preserve 32 bit alignment */			if (w > 2 && nimage & 2)				nimage += 2;			nimage += pr_product(w, h);		}	/* allocate space for pixfont, pixrects, and images */	nimage += nfont;#ifndef	NO_SHARED_LIB_FONTS	pf = pf_alloc_font(fontname, nimage, from_vm);	if ((pf == (Pixfont *)0) || (*from_vm && (_use_vm == 0))) {		goto bad;	/* bit of a misnomer */	} else {#else	if (pf = (Pixfont *) calloc(1, nimage)) {#endif		pf->pf_defaultsize.x = defx;		pf->pf_defaultsize.y = defy;		/* construct pixfont */		if (pf_build(fontf, disp, &pf->pf_char[0], 			(caddr_t) (pf + 1), PTR_ADD(pf, nfont))) {			free((char *) pf);			pf = 0;		}	}bad:	(void) fclose(fontf);	return pf;}staticpf_build(fontf, disp, pc, data, image)	FILE *fontf;	register struct dispatch *disp;	struct pixchar *pc;	caddr_t data;	char *image;{	int nchar;	register unsigned short addr = 0;	/* hack to recycle registers */	register caddr_t Aptr, Bptr;#define	Apc	((struct pixchar *) Aptr)#define	Bpr	((Pixrect *) Bptr)#define Aprd	((struct mpr_data *) Aptr)#define	Bimage	((char *) Bptr)#define	Afile	((FILE *) Aptr)	for (nchar = NUM_DISPATCH; --nchar >= 0; disp++, pc++)		if (disp->nbytes) {			register int w, h, pad;			/* create pixchar */			Aptr = (caddr_t) pc;			w = disp->left;			Apc->pc_home.x = -w;			w += disp->right;			h = disp->up;			Apc->pc_home.y = -h;			h += disp->down;			Apc->pc_adv.x = disp->width;			Apc->pc_adv.y = 0;			/* create pixrect */			Bptr = (caddr_t) data;			Apc->pc_pr = Bpr;			Bpr->pr_ops = &mem_ops;			Bpr->pr_size.x = w;			Bpr->pr_size.y = h;			Bpr->pr_depth = 1;			/* create pixrect data */			Aptr = (caddr_t) (Bpr + 1);			Bpr->pr_data = (caddr_t) Aprd;			w = (w + 7) >> 3;			pad = w <= 2 ? 2 : w + 3 & ~3;			Aprd->md_linebytes = pad;			Bptr = (caddr_t) image;			if (pad > 2 && (int) Bptr & 2)				Bptr += 2;			Aprd->md_image = (short *) Bimage;			Aprd->md_flags = w <= 2 ? MP_FONT : 0;			data = (caddr_t) (Aprd + 1);			Aptr = (caddr_t) fontf;			if (addr != disp->addr) {				(void) fseek(Afile, 					(long) (sizeof (struct header) + 					sizeof (struct dispatch) * 						NUM_DISPATCH + 					disp->addr),					0);				addr = disp->addr;			}#ifdef MUTANT			/* check for mutant short-padded vfont */			if (w & 1 && pr_product(w + 1, h) == disp->nbytes)				w++;#endif MUTANT			pad -= w;			while (--h >= 0) {				PR_LOOPP(w - 1,					*Bimage = getc(Afile);					Bptr++);				Bptr += pad;				addr += w;			}			image = Bptr;		}	return ferror(Afile) || feof(Afile);}

⌨️ 快捷键说明

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