xref: /plan9/sys/src/libframe/frutil.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 int
_frcanfit(Frame * f,Point pt,Frbox * b)9 _frcanfit(Frame *f, Point pt, Frbox *b)
10 {
11 	int left, w, nr;
12 	uchar *p;
13 	Rune r;
14 
15 	left = f->r.max.x-pt.x;
16 	if(b->nrune < 0)
17 		return b->minwid <= left;
18 	if(left >= b->wid)
19 		return b->nrune;
20 	for(nr=0,p=b->ptr; *p; p+=w,nr++){
21 		r = *p;
22 		if(r < Runeself)
23 			w = 1;
24 		else
25 			w = chartorune(&r, (char*)p);
26 		left -= stringnwidth(f->font, (char*)p, 1);
27 		if(left < 0)
28 			return nr;
29 	}
30 	drawerror(f->display, "_frcanfit can't");
31 	return 0;
32 }
33 
34 void
_frcklinewrap(Frame * f,Point * p,Frbox * b)35 _frcklinewrap(Frame *f, Point *p, Frbox *b)
36 {
37 	if((b->nrune<0? b->minwid : b->wid) > f->r.max.x-p->x){
38 		p->x = f->r.min.x;
39 		p->y += f->font->height;
40 	}
41 }
42 
43 void
_frcklinewrap0(Frame * f,Point * p,Frbox * b)44 _frcklinewrap0(Frame *f, Point *p, Frbox *b)
45 {
46 	if(_frcanfit(f, *p, b) == 0){
47 		p->x = f->r.min.x;
48 		p->y += f->font->height;
49 	}
50 }
51 
52 void
_fradvance(Frame * f,Point * p,Frbox * b)53 _fradvance(Frame *f, Point *p, Frbox *b)
54 {
55 	if(b->nrune<0 && b->bc=='\n'){
56 		p->x = f->r.min.x;
57 		p->y += f->font->height;
58 	}else
59 		p->x += b->wid;
60 }
61 
62 int
_frnewwid(Frame * f,Point pt,Frbox * b)63 _frnewwid(Frame *f, Point pt, Frbox *b)
64 {
65 	b->wid = _frnewwid0(f, pt, b);
66 	return b->wid;
67 }
68 
69 int
_frnewwid0(Frame * f,Point pt,Frbox * b)70 _frnewwid0(Frame *f, Point pt, Frbox *b)
71 {
72 	int c, x;
73 
74 	c = f->r.max.x;
75 	x = pt.x;
76 	if(b->nrune>=0 || b->bc!='\t')
77 		return b->wid;
78 	if(x+b->minwid > c)
79 		x = pt.x = f->r.min.x;
80 	x += f->maxtab;
81 	x -= (x-f->r.min.x)%f->maxtab;
82 	if(x-pt.x<b->minwid || x>c)
83 		x = pt.x+b->minwid;
84 	return x-pt.x;
85 }
86 
87 void
_frclean(Frame * f,Point pt,int n0,int n1)88 _frclean(Frame *f, Point pt, int n0, int n1)	/* look for mergeable boxes */
89 {
90 	Frbox *b;
91 	int nb, c;
92 
93 	c = f->r.max.x;
94 	for(nb=n0; nb<n1-1; nb++){
95 		b = &f->box[nb];
96 		_frcklinewrap(f, &pt, b);
97 		while(b[0].nrune>=0 && nb<n1-1 && b[1].nrune>=0 && pt.x+b[0].wid+b[1].wid<c){
98 			_frmergebox(f, nb);
99 			n1--;
100 			b = &f->box[nb];
101 		}
102 		_fradvance(f, &pt, &f->box[nb]);
103 	}
104 	for(; nb<f->nbox; nb++){
105 		b = &f->box[nb];
106 		_frcklinewrap(f, &pt, b);
107 		_fradvance(f, &pt, &f->box[nb]);
108 	}
109 	f->lastlinefull = 0;
110 	if(pt.y >= f->r.max.y)
111 		f->lastlinefull = 1;
112 }
113