365 lines · 6.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include <draw.h>#include <bio.h>#include <keyboard.h>#include <mouse.h> #define MIN(a,b) ((a)<=(b)?(a):(b))#define MAX(a,b) ((a)>=(b)?(a):(b)) typedef struct Fontdir Fontdir; struct Fontdir {	char *name;	char *prefix;	char **fonts;	int nfonts;	int isttf;	union {		int ifont;		int sz;	};}; enum{	Ckey,	Cmouse,	Cresize,	Numchan, 	Ttfdefsz = 16,}; static char *textdef[] = {	"Cwm fjord bank glyphs vext quiz!",	"Gud hjälpe Zorns mö qvickt få byxa?",	"Разъярённый чтец эгоистично бьёт пятью",	"жердями шустрого фехтовальщика.",	"",	"static int",	"dosomestuff(Stuff *s, char *t, int n)",	"{",	"    if(s == nil && (t == nil || n < 1))",	"        return 0;",	"    fprint(2, \"# %c\\n\", t[0]);",	"    return dostuff(s) || dot(t, n);",	"}",	nil}; static char **text = textdef; static char *prefixes[] = {	"/lib/font/bit",	"/lib/font/ttf",}; static Font *f;static Fontdir *dirs, *cdir;static int ndirs, idir;static char lasterr[256];int mainstacksize = 32768; static voidredraw(void){	Point p;	int i, w, maxw;	char t[256]; 	lockdisplay(display);	draw(screen, screen->r, display->white, nil, ZP);	p = screen->r.min; 	if(f == nil){		p.x += Dx(screen->r)/2 - stringwidth(font, lasterr)/2;		p.y += Dy(screen->r)/2 - font->height/2;		string(screen, p, display->black, ZP, font, lasterr);	}else{		maxw = 0;		for(i = 0; text[i] != nil; i++){			if((w = stringwidth(f, text[i])) > maxw)				maxw = w;		}		p.x += Dx(screen->r)/2 - maxw/2;		p.y += Dy(screen->r)/2 - i*f->height/2; 		for(i = 0; text[i] != nil; i++){			string(screen, p, display->black, ZP, f, text[i]);			p.y += f->height;		} 	} 	if(cdir->isttf)		snprint(t, sizeof(t), "/n/ttf/%s.%d/font", cdir->name, cdir->sz);	else		snprint(t, sizeof(t), "%s/%s", cdir->name, cdir->fonts[cdir->ifont]);	p = screen->r.max;	p.x -= Dx(screen->r)/2 + stringwidth(font, t)/2;	p.y -= font->height;	string(screen, p, display->black, ZP, font, t); 	flushimage(display, 1);	unlockdisplay(display);} static intfcmp(void *a, void *b){	return strcmp(*(char**)a, *(char**)b);} static intfontdir(char *t, int f, Fontdir *fdir){	Dir *d;	int doff, k;	long i, n; 	k = strlen(t);	if(k > 4 && (cistrcmp(&t[k-4], ".ttf") == 0 || cistrcmp(&t[k-4], ".otf") == 0)){		fdir->nfonts = 1;		fdir->sz = Ttfdefsz;		fdir->isttf = 1;		return 0;	} 	if((n = dirreadall(f, &d)) < 1)		return -1;	doff = strlen(t);	t[doff++] = '/';	for(i = 0; i < n; i++){		if((k = strlen(d[i].name)) < 5 || strcmp(&d[i].name[k-5], ".font") != 0)			continue;		if((fdir->fonts = realloc(fdir->fonts, sizeof(*fdir->fonts)*(fdir->nfonts+1))) == nil)			sysfatal("no memory");		d[i].name[k-5] = 0;		strcpy(t+doff, d[i].name);		fdir->fonts[fdir->nfonts++] = strdup(t+doff);	}	free(d);	if(fdir->nfonts > 0)		qsort(fdir->fonts, fdir->nfonts, sizeof(*fdir->fonts), fcmp); 	return 0;} static intdcmp(void *a_, void *b_){	Fontdir *a, *b; 	a = (Fontdir*)a_;	b = (Fontdir*)b_;	return strcmp(a->name, b->name);} static voidfindfonts(char *prefix){	Dir *d, *din;	int f, fin, doff;	long i, n;	char t[1024]; 	doff = sprint(t, "%s", prefix);	t[doff++] = '/';	t[doff] = 0;	if((f = open(t, OREAD)) < 0){		fprint(2, "font dir: %r\n");		return;	}	if((n = dirreadall(f, &d)) < 1){		fprint(2, "%s: no fonts\n", t);		close(f);		return;	}	close(f);	for(i = 0; i < n; i++){		strcpy(t+doff, d[i].name);		if((fin = open(t, OREAD)) < 0)			continue;		if((din = dirfstat(fin)) != nil){			if((dirs = realloc(dirs, sizeof(Fontdir)*(ndirs+1))) == nil)				sysfatal("no memory");			memset(&dirs[ndirs], 0, sizeof(Fontdir));			dirs[ndirs].prefix = prefix;			if(fontdir(t, fin, &dirs[ndirs]) == 0 && dirs[ndirs].nfonts > 0)				dirs[ndirs++].name = strdup(d[i].name);			free(din);		}		close(fin);	}	free(d);} static voidnewfont(void){	char t[512]; 	lockdisplay(display);	if(f != nil)		freefont(f);	if(cdir->isttf)		snprint(t, sizeof(t), "/n/ttf/%s.%d/font", cdir->name, cdir->sz);	else		snprint(t, sizeof(t), "%s/%s/%s.font", cdir->prefix, cdir->name, cdir->fonts[cdir->ifont]);	if((f = openfont(display, t)) == nil)		snprint(lasterr, sizeof(lasterr), "%r");	unlockdisplay(display);} static char *dirgen(int i){	return i < ndirs ? dirs[i].name : nil;} static char *fontgen(int i){	return i < cdir->nfonts ? cdir->fonts[i] : nil;} static voidusage(void){	print("usage: %s [FILE]\n", argv0);	threadexitsall("usage");} static voidloadtext(int f){	Biobuf b;	int i; 	if(f < 0 || Binit(&b, f, OREAD) != 0)		sysfatal("loadtext: %r"); 	text = nil;	for(i = 0; i < 256; i++){		if((text = realloc(text, (i+1)*sizeof(char*))) == nil)			sysfatal("memory");		if((text[i] = Brdstr(&b, '\n', 1)) == nil)			break;	} 	close(f);} voidthreadmain(int argc, char **argv){	Mousectl *mctl;	Keyboardctl *kctl;	Rune r;	Mouse m;	Menu menu;	Alt a[Numchan+1] = {		[Ckey] = {nil, &r, CHANRCV},		[Cmouse] = {nil, &m, CHANRCV },		[Cresize] = {nil, nil, CHANRCV},		{nil, nil, CHANEND},	};	int n; 	ARGBEGIN{	default:		usage();		break;	}ARGEND; 	if(argc > 1)		usage();	else if(argc == 1)		loadtext(strcmp(argv[0], "-") == 0 ? 0 : open(argv[0], OREAD)); 	for(n = 0; n < nelem(prefixes); n++)		findfonts(prefixes[n]);	if(ndirs < 1)		sysfatal("no fonts");	qsort(dirs, ndirs, sizeof(*dirs), dcmp); 	if(initdraw(nil, nil, "fontsel") < 0)		sysfatal("initdraw: %r");	if((kctl = initkeyboard(nil)) == nil)		sysfatal("initkeyboard: %r");	a[Ckey].c = kctl->c;	if((mctl = initmouse(nil, screen)) == nil)		sysfatal("initmouse: %r");	a[Cmouse].c = mctl->c;	a[Cresize].c = mctl->resizec;	display->locking = 1;	unlockdisplay(display); 	memset(&menu, 0, sizeof(menu));	cdir = &dirs[0];	newfont();	redraw(); 	for(;;){		switch(alt(a)){		case -1:			goto end; 		case Ckey:			switch (r) {			case Kdel:			case 'q':				goto end;			case '-':				cdir->ifont = MAX(cdir->isttf ? 6 : 0, cdir->ifont-1);				newfont();				redraw();				break;			case '+':				cdir->ifont = MIN(cdir->isttf ? 256 : cdir->nfonts-1, cdir->ifont+1);				newfont();				redraw();				break;			}			break; 		case Cmouse:			if(m.buttons == 2){				menu.gen = dirgen;				menu.lasthit = idir;				if((n = menuhit(2, mctl, &menu, nil)) >= 0){					idir = n;					cdir = &dirs[idir];					newfont();					redraw();				}			}else if(m.buttons == 4 && cdir->isttf == 0){				menu.gen = fontgen;				menu.lasthit = cdir->ifont;				if((n = menuhit(3, mctl, &menu, nil)) >= 0){					cdir->ifont = n;					newfont();					redraw();				}			}			break; 		case Cresize:			getwindow(display, Refnone);			redraw();			break;		}	} end:	if(f != nil){		if(cdir->isttf)			print("/n/ttf/%s.%d/font\n", cdir->name, cdir->sz);		else			print("%s/%s/%s.font\n", cdir->prefix, cdir->name, cdir->fonts[cdir->ifont]);	}	threadexitsall(nil);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t