| #include <u.h> | 
 | #include <libc.h> | 
 | #include <draw.h> | 
 | #include <mouse.h> | 
 | #include <frame.h> | 
 |  | 
 | Point | 
 | _frptofcharptb(Frame *f, ulong p, Point pt, int bn) | 
 | { | 
 | 	uchar *s; | 
 | 	Frbox *b; | 
 | 	int w, l; | 
 | 	Rune r; | 
 |  | 
 | 	for(b = &f->box[bn]; bn<f->nbox; bn++,b++){ | 
 | 		_frcklinewrap(f, &pt, b); | 
 | 		if(p < (l=NRUNE(b))){ | 
 | 			if(b->nrune > 0) | 
 | 				for(s=b->ptr; p>0; s+=w, p--){ | 
 | 					if((r = *s) < Runeself) | 
 | 						w = 1; | 
 | 					else | 
 | 						w = chartorune(&r, (char*)s); | 
 | 					pt.x += stringnwidth(f->font, (char*)s, 1); | 
 | 					if(r==0 || pt.x>f->r.max.x) | 
 | 						drawerror(f->display, "frptofchar"); | 
 | 				} | 
 | 			break; | 
 | 		} | 
 | 		p -= l; | 
 | 		_fradvance(f, &pt, b); | 
 | 	} | 
 | 	return pt; | 
 | } | 
 |  | 
 | Point | 
 | frptofchar(Frame *f, ulong p) | 
 | { | 
 | 	return _frptofcharptb(f, p, f->r.min, 0); | 
 | } | 
 |  | 
 | Point | 
 | _frptofcharnb(Frame *f, ulong p, int nb)	/* doesn't do final _fradvance to next line */ | 
 | { | 
 | 	Point pt; | 
 | 	int nbox; | 
 |  | 
 | 	nbox = f->nbox; | 
 | 	f->nbox = nb; | 
 | 	pt = _frptofcharptb(f, p, f->r.min, 0); | 
 | 	f->nbox = nbox; | 
 | 	return pt; | 
 | } | 
 |  | 
 | static | 
 | Point | 
 | _frgrid(Frame *f, Point p) | 
 | { | 
 | 	p.y -= f->r.min.y; | 
 | 	p.y -= p.y%f->font->height; | 
 | 	p.y += f->r.min.y; | 
 | 	if(p.x > f->r.max.x) | 
 | 		p.x = f->r.max.x; | 
 | 	return p; | 
 | } | 
 |  | 
 | ulong | 
 | frcharofpt(Frame *f, Point pt) | 
 | { | 
 | 	Point qt; | 
 | 	int w, bn; | 
 | 	uchar *s; | 
 | 	Frbox *b; | 
 | 	ulong p; | 
 | 	Rune r; | 
 |  | 
 | 	pt = _frgrid(f, pt); | 
 | 	qt = f->r.min; | 
 | 	for(b=f->box,bn=0,p=0; bn<f->nbox && qt.y<pt.y; bn++,b++){ | 
 | 		_frcklinewrap(f, &qt, b); | 
 | 		if(qt.y >= pt.y) | 
 | 			break; | 
 | 		_fradvance(f, &qt, b); | 
 | 		p += NRUNE(b); | 
 | 	} | 
 | 	for(; bn<f->nbox && qt.x<=pt.x; bn++,b++){ | 
 | 		_frcklinewrap(f, &qt, b); | 
 | 		if(qt.y > pt.y) | 
 | 			break; | 
 | 		if(qt.x+b->wid > pt.x){ | 
 | 			if(b->nrune < 0) | 
 | 				_fradvance(f, &qt, b); | 
 | 			else{ | 
 | 				s = b->ptr; | 
 | 				for(;;){ | 
 | 					if((r = *s) < Runeself) | 
 | 						w = 1; | 
 | 					else | 
 | 						w = chartorune(&r, (char*)s); | 
 | 					if(r == 0) | 
 | 						drawerror(f->display, "end of string in frcharofpt"); | 
 | 					qt.x += stringnwidth(f->font, (char*)s, 1); | 
 | 					s += w; | 
 | 					if(qt.x > pt.x) | 
 | 						break; | 
 | 					p++; | 
 | 				} | 
 | 			} | 
 | 		}else{ | 
 | 			p += NRUNE(b); | 
 | 			_fradvance(f, &qt, b); | 
 | 		} | 
 | 	} | 
 | 	return p; | 
 | } |