henesyinit from p9fce6d0435 years agoHistory
410 lines · 10.2 KB · C
RawDownload
/* * Display pages of unicode character set */#include <u.h>#include <libc.h>#include <libg.h>#define	SIZE	24#define	NROW	16#define	NCOL	16#define	GAP	16typedef struct Page Page;struct Page{	Rectangle r;	int first, step;};Page whole, detail;int snarf;/* * The following table is abstracted from *	The Unicode Standard *	Worldwide Character Encoding *	Version 1.0, Volume 1 */char *pagename[256]={[0x00] "Control/ASCII/Control/Latin1",[0x01] "European Latin/Extended Latin",[0x02] "Standard Phonetic/Modifier Letters",[0x03] "Generic Diacritical Marks/Greek",[0x04] "Cyrillic",[0x05] "Armenian/Hebrew",[0x06] "Arabic",[0x07] "Unassigned, Reserved for Right-To-Left Characters",[0x08] "Unassigned, Reserved for Right-To-Left Characters",[0x09] "Devanagari/Bengali",[0x0a] "Gurmukhi/Gujarati",[0x0b] "Oriya/Tamil",[0x0c] "Telugu/Kannada",[0x0d] "Malayalam",[0x0e] "Thai/Lao",[0x10] "Tibetan/Georgian",[0x20] "General Punctuation/Superscripts and Subscripts/Currency Symbols/Diacritical Marks for Symbols",[0x21] "Letterlike Symbols/Number Forms/Arrows",[0x22] "Mathematical Operators",[0x23] "Miscellaneous Technical",[0x24] "Pictures for Control Codes/Optical Character Recognition/Enclosed Alphanumerics",[0x25] "Form and Chart Components/Blocks/Geometric Shapes",[0x26] "Miscellaneous Dingbats",[0x27] "Zapf Dingbats",[0x30] "CJK Symbols and Punctuation/Hiragana/Katakana",[0x31] "Bopomofo/Hangul Elements/CJK Miscellaneous",[0x32] "Enclosed CJK Letters and Ideographs",[0x33] "CJK Squared Words/CJK Squared Abbreviations",[0x34] "Korean Hangul Syllables",[0x35] "Korean Hangul Syllables",[0x36] "Korean Hangul Syllables",[0x37] "Korean Hangul Syllables",[0x38] "Korean Hangul Syllables",[0x39] "Korean Hangul Syllables",[0x3a] "Korean Hangul Syllables",[0x3b] "Korean Hangul Syllables",[0x3c] "Korean Hangul Syllables",[0x3d] "Korean Hangul Syllables",[0x4e] "CJK Ideographs",[0x4f] "CJK Ideographs",[0x50] "CJK Ideographs",[0x51] "CJK Ideographs",[0x52] "CJK Ideographs",[0x53] "CJK Ideographs",[0x54] "CJK Ideographs",[0x55] "CJK Ideographs",[0x56] "CJK Ideographs",[0x57] "CJK Ideographs",[0x58] "CJK Ideographs",[0x59] "CJK Ideographs",[0x5a] "CJK Ideographs",[0x5b] "CJK Ideographs",[0x5c] "CJK Ideographs",[0x5d] "CJK Ideographs",[0x5e] "CJK Ideographs",[0x5f] "CJK Ideographs",[0x60] "CJK Ideographs",[0x61] "CJK Ideographs",[0x62] "CJK Ideographs",[0x63] "CJK Ideographs",[0x64] "CJK Ideographs",[0x65] "CJK Ideographs",[0x66] "CJK Ideographs",[0x67] "CJK Ideographs",[0x68] "CJK Ideographs",[0x69] "CJK Ideographs",[0x6a] "CJK Ideographs",[0x6b] "CJK Ideographs",[0x6c] "CJK Ideographs",[0x6d] "CJK Ideographs",[0x6e] "CJK Ideographs",[0x6f] "CJK Ideographs",[0x70] "CJK Ideographs",[0x71] "CJK Ideographs",[0x72] "CJK Ideographs",[0x73] "CJK Ideographs",[0x74] "CJK Ideographs",[0x75] "CJK Ideographs",[0x76] "CJK Ideographs",[0x77] "CJK Ideographs",[0x78] "CJK Ideographs",[0x79] "CJK Ideographs",[0x7a] "CJK Ideographs",[0x7b] "CJK Ideographs",[0x7c] "CJK Ideographs",[0x7d] "CJK Ideographs",[0x7e] "CJK Ideographs",[0x7f] "CJK Ideographs",[0x80] "CJK Ideographs",[0x81] "CJK Ideographs",[0x82] "CJK Ideographs",[0x83] "CJK Ideographs",[0x84] "CJK Ideographs",[0x85] "CJK Ideographs",[0x86] "CJK Ideographs",[0x87] "CJK Ideographs",[0x88] "CJK Ideographs",[0x89] "CJK Ideographs",[0x8a] "CJK Ideographs",[0x8b] "CJK Ideographs",[0x8c] "CJK Ideographs",[0x8d] "CJK Ideographs",[0x8e] "CJK Ideographs",[0x8f] "CJK Ideographs",[0x90] "CJK Ideographs",[0x91] "CJK Ideographs",[0x92] "CJK Ideographs",[0x93] "CJK Ideographs",[0x94] "CJK Ideographs",[0x95] "CJK Ideographs",[0x96] "CJK Ideographs",[0x97] "CJK Ideographs",[0x98] "CJK Ideographs",[0x99] "CJK Ideographs",[0x9a] "CJK Ideographs",[0x9b] "CJK Ideographs",[0x9c] "CJK Ideographs",[0x9d] "CJK Ideographs",[0x9e] "CJK Ideographs",[0x9f] "CJK Ideographs",[0xe8] "Private Use Area",[0xe9] "Private Use Area",[0xea] "Private Use Area",[0xeb] "Private Use Area",[0xec] "Private Use Area",[0xed] "Private Use Area",[0xee] "Private Use Area",[0xef] "Private Use Area",[0xf0] "Private Use Area",[0xf1] "Private Use Area",[0xf2] "Private Use Area",[0xf3] "Private Use Area",[0xf4] "Private Use Area",[0xf5] "Private Use Area",[0xf6] "Private Use Area",[0xf7] "Private Use Area",[0xf8] "Private Use Area",[0xf9] "Private Use Area",[0xfa] "Private Use Area",[0xfb] "Private Use Area",[0xfc] "Private Use Area",[0xfd] "Private Use Area",[0xfe] "CNS 11643 Compatibility/Small Variants/Basic Glyphs for Arabic Language",[0xff] "Halfwidth and Fullwidth Variants/Special",};void showsnarf(void);void seepage(Page *pg){	Point p;	int c;	char buf[10];	bitblt(&screen, sub(pg->r.min, Pt(2, 2)), &screen, inset(pg->r, -2), Zero);	for(p.x=0,c=pg->first;p.x!=NCOL;p.x++){		for(p.y=0;p.y!=NROW;p.y++,c+=pg->step){			sprint(buf, "%C", c);			string(&screen, add(pg->r.min, mul(p, SIZE)), font, buf, S);		}		buf[0]="0123456789abcdef"[p.x];		buf[1]='\0';		string(&screen, add(pg->r.min, mul(Pt(p.x, NCOL), SIZE)), font, buf, S);		string(&screen, add(pg->r.min, mul(Pt(NCOL, p.x), SIZE)), font, buf, S);	}	bflush();}void ereshaped(Rectangle r){	screen.r=r;	screen.clipr=inset(screen.r, 2);	bitblt(&screen, screen.clipr.min, &screen, screen.clipr, Zero);	whole.r.min=sub(div(add(r.min, r.max), 2), Pt((NCOL+1)*SIZE+GAP, (NROW+1)*SIZE/2));	whole.r.max=add(whole.r.min, Pt((NCOL+1)*SIZE, (NROW+1)*SIZE));	whole.first=0;	whole.step=NROW*NCOL;	detail.r.min=Pt(whole.r.max.x+2*GAP, whole.r.min.y);	detail.r.max=add(detail.r.min, Pt((NCOL+1)*SIZE, (NROW+1)*SIZE));	/* don't set detail.first, so we see the same page as before */	detail.step=1;	seepage(&whole);	seepage(&detail);	showsnarf();}int hit(Point p, Page *pg){	if(!ptinrect(p, pg->r)) return -1;	p=div(sub(p, pg->r.min), SIZE);	if(p.y>=NROW || p.x>=NCOL) return -1;	return p.x*NROW+p.y;}enum{	TRUNC,	EXIT};char *item3[]={	[TRUNC] "empty snarf",	[EXIT]  "exit",	0};Menu menu3={item3};Cursor confirmcurs={	0, 0,	0x0F, 0xBF, 0x0F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF,	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,	0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF,	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 	0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,	0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,	0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,	0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90};/* * Wait for mouse down */void mdown(Mouse *mp){	while(mp->buttons==0) *mp=emouse();}/* * Wait for mouse up */void mup(Mouse *mp){	while(mp->buttons!=0) *mp=emouse();}/* * wait for confirming click on button b */int confirm(int b, Mouse *mp){	int down;	cursorswitch(&confirmcurs);	mup(mp);	mdown(mp);	down=mp->buttons==(1<<(b-1));	mup(mp);	cursorswitch(0);	return down;}/* * Return the offset of the first byte of the line containing byte offs in file fd. * Fill buf with the line. */int line(int offs, int fd, char *buf, int nbuf){	char *nl;	int n, nread;	nread=nbuf-1;		/* save space to add a nul */	while(offs){		if(offs<nread){			nread=offs;			offs=0;		}		else			offs-=nread;		seek(fd, offs, 0);		n=read(fd, buf, nread);		if(n<=0) return -1;		/* should never happen */		buf[n]='\0';		nl=strrchr(buf, '\n');		if(nl){			offs+=(nl-buf)+1;			break;		}	}	seek(fd, offs, 0);	n=read(fd, buf, nbuf-1);	if(n<=0) return -1;	/* Really(!) should never happen */	buf[n]='\0';	nl=strchr(buf, '\n');	if(nl) *nl='\0';	return offs;}int look(int fd, char *key, char *out, int nout){	long lwb, mid, upb;	Dir d;	int nkey;	if(nout<2) return 0;		/* need at least space for \n\0 */	if(dirfstat(fd, &d)<0) return 0;	nkey=strlen(key);	lwb=line(0, fd, out, nout);	if(lwb<0) return 0;	switch(strncmp(out, key, nkey)){	case -1: break;	case 0: return 1;	case 1: return 0;	}	upb=line(d.length-1, fd, out, nout);	if(upb<0) return 0;	switch(strncmp(out, key, nkey)){	case -1: return 0;	case 0: return 1;	case 1: break;	}	while(lwb<=upb){		mid=line((lwb+upb)/2, fd, out, nout);		if(mid<0) return 0;		switch(strncmp(out, key, nkey)){		case -1: lwb=mid+strlen(out)+1; break;		case  0: return 1;		case  1: upb=mid-1; break;		}	}	return 0;}#define	NLINE	2000void showsnarf(void){	char line[NLINE];	Point p;	int n;	if(snarf>=0){		strcpy(line, "snarf: ");		seek(snarf, 0, 0);		n=read(snarf, line+7, NLINE-8);		if(n<0) n=0;		line[n+7]='\0';	}	else		strcpy(line, "no /dev/snarf");	p=string(&screen, add(screen.clipr.min, Pt(4, 6+font->height)), font, line, S);	bitblt(&screen, p, &screen, Rect(p.x, p.y, screen.clipr.max.x, p.y+font->height),		Zero);}void main(int argc, char *argv[]){	Mouse m;	Point p;	int h, n;	char buf[100+NLINE];	char line[NLINE];	int unames;	unames=open("/lib/unicode", OREAD);	snarf=open("/dev/snarf", ORDWR);	binit(0, argc>1?argv[1]:0, argv[0]);	einit(Emouse|Ekeyboard);	ereshaped(screen.r);	for(;;){		m=emouse();		switch(m.buttons){		case 1:		case 2:			h=hit(m.xy, &whole);			if(h>=0){				sprint(buf, "%x%xxx %s", h/NROW, h%NROW,					pagename[h]?pagename[h]:"");				p=string(&screen, add(screen.clipr.min, Pt(4, 4)),					font, buf, S);				bitblt(&screen, p, &screen,					Rect(p.x,p.y, screen.clipr.max.x,p.y+font->height),					Zero);				detail.first=h*NROW*NCOL;				seepage(&detail);				break;			}			h=hit(m.xy, &detail);			if(h<0) break;			sprint(buf, "%x%x%x%x",				detail.first/(NROW*NROW)/NROW,				detail.first/(NROW*NROW)%NROW,				h/NROW, h%NROW);			if(unames>=0 && look(unames, buf, line, NLINE) && strlen(line)>5){				strcat(buf, " ");				strcat(buf, line+5);			}			p=string(&screen, add(screen.clipr.min, Pt(4, 4)),				font, buf, S);			if(p.x<screen.clipr.max.x)				bitblt(&screen, p, &screen,					Rect(p.x,p.y, screen.clipr.max.x,p.y+font->height),					Zero);			if(m.buttons!=2) break;			if(snarf>=0){				/* there appears to be a bug in /dev/snarf */				seek(snarf, 0, 0);				n=read(snarf, buf, NLINE);				seek(snarf, 0, 0);				write(snarf, buf, n);				fprint(snarf, "%C", detail.first+h);			}			break;		case 4:			switch(menuhit(3, &m, &menu3)){			case TRUNC:				close(snarf);				snarf=create("/dev/snarf", ORDWR, 0666);				break;			case EXIT:				if(confirm(3, &m)) exits("");				break;			}		}		showsnarf();		mup(&m);	}}