xref: /plan9/sys/src/libframe/frptofchar.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <frame.h>
7 
8 Point
_frptofcharptb(Frame * f,ulong p,Point pt,int bn)9 _frptofcharptb(Frame *f, ulong p, Point pt, int bn)
10 {
11 	uchar *s;
12 	Frbox *b;
13 	int w, l;
14 	Rune r;
15 
16 	for(b = &f->box[bn]; bn<f->nbox; bn++,b++){
17 		_frcklinewrap(f, &pt, b);
18 		if(p < (l=NRUNE(b))){
19 			if(b->nrune > 0)
20 				for(s=b->ptr; p>0; s+=w, p--){
21 					if((r = *s) < Runeself)
22 						w = 1;
23 					else
24 						w = chartorune(&r, (char*)s);
25 					pt.x += stringnwidth(f->font, (char*)s, 1);
26 					if(r==0 || pt.x>f->r.max.x)
27 						drawerror(f->display, "frptofchar");
28 				}
29 			break;
30 		}
31 		p -= l;
32 		_fradvance(f, &pt, b);
33 	}
34 	return pt;
35 }
36 
37 Point
frptofchar(Frame * f,ulong p)38 frptofchar(Frame *f, ulong p)
39 {
40 	return _frptofcharptb(f, p, f->r.min, 0);
41 }
42 
43 Point
_frptofcharnb(Frame * f,ulong p,int nb)44 _frptofcharnb(Frame *f, ulong p, int nb)	/* doesn't do final _fradvance to next line */
45 {
46 	Point pt;
47 	int nbox;
48 
49 	nbox = f->nbox;
50 	f->nbox = nb;
51 	pt = _frptofcharptb(f, p, f->r.min, 0);
52 	f->nbox = nbox;
53 	return pt;
54 }
55 
56 static
57 Point
_frgrid(Frame * f,Point p)58 _frgrid(Frame *f, Point p)
59 {
60 	p.y -= f->r.min.y;
61 	p.y -= p.y%f->font->height;
62 	p.y += f->r.min.y;
63 	if(p.x > f->r.max.x)
64 		p.x = f->r.max.x;
65 	return p;
66 }
67 
68 ulong
frcharofpt(Frame * f,Point pt)69 frcharofpt(Frame *f, Point pt)
70 {
71 	Point qt;
72 	int w, bn;
73 	uchar *s;
74 	Frbox *b;
75 	ulong p;
76 	Rune r;
77 
78 	pt = _frgrid(f, pt);
79 	qt = f->r.min;
80 	for(b=f->box,bn=0,p=0; bn<f->nbox && qt.y<pt.y; bn++,b++){
81 		_frcklinewrap(f, &qt, b);
82 		if(qt.y >= pt.y)
83 			break;
84 		_fradvance(f, &qt, b);
85 		p += NRUNE(b);
86 	}
87 	for(; bn<f->nbox && qt.x<=pt.x; bn++,b++){
88 		_frcklinewrap(f, &qt, b);
89 		if(qt.y > pt.y)
90 			break;
91 		if(qt.x+b->wid > pt.x){
92 			if(b->nrune < 0)
93 				_fradvance(f, &qt, b);
94 			else{
95 				s = b->ptr;
96 				for(;;){
97 					if((r = *s) < Runeself)
98 						w = 1;
99 					else
100 						w = chartorune(&r, (char*)s);
101 					if(r == 0)
102 						drawerror(f->display, "end of string in frcharofpt");
103 					qt.x += stringnwidth(f->font, (char*)s, 1);
104 					s += w;
105 					if(qt.x > pt.x)
106 						break;
107 					p++;
108 				}
109 			}
110 		}else{
111 			p += NRUNE(b);
112 			_fradvance(f, &qt, b);
113 		}
114 	}
115 	return p;
116 }
117