|
|
1.1 root 1: #include "jerq.h"
2:
3: #ifdef SUNTOOLS
4: #undef F_STORE
5: #define F_STORE (PIX_DONTCLIP|PIX_SRC)
6: #endif SUNTOOLS
7:
8: #define scale(x, inmin, inmax, outmin, outmax)\
9: (outmin + muldiv(x-inmin,outmax-outmin,inmax-inmin))
10:
11: #define bound(x, low, high) min(high, max( low, x ))
12:
13: #define DISPLAY 16
14: #define BARWIDTH 18
15:
16: static char **table;
17: static char *
18: tablegen(i)
19: {
20: return table[i];
21: }
22:
23: menuhit (m, but)
24: register Menu *m;
25: int but;
26: {
27: register int width, i, j, top, newtop, hit, newhit, items;
28: register int lines, length;
29: Point p, q, savep, baro, barc;
30: Rectangle sr, tr, mr; /* scroll, text, menu */
31: register Bitmap *b;
32: register char *s, *(*generator)(), *from, *to, fill[64];
33: Font *font = &defont;
34: int spacing = fontheight(font);
35: int charwidth = fontwidth(font);
36:
37: #define sro sr.origin
38: #define src sr.corner
39: #define tro tr.origin
40: #define trc tr.corner
41: #define mro mr.origin
42: #define mrc mr.corner
43:
44: generator = (table=m->item) ? tablegen : m->generator;
45: length = width = items = 0;
46: for( ; s=(*generator)(items); ++items) {
47: length = max(length, strlen(s));
48: width = max(width, strwidth(font,s));
49: }
50: if(items == 0){
51: while(button(but));
52: return -1;
53: }
54: Jscreengrab();
55: width += 10;
56: sro.x = sro.y = src.x = tro.x = mro.x = mro.y = 0;
57: if(items <= DISPLAY)
58: lines = items;
59: else{
60: lines = DISPLAY;
61: tro.x = src.x = BARWIDTH;
62: sro.x = sro.y = 1;
63: }
64: tro.y = 1;
65: mrc = trc = add(Pt(tro.x, mro.y), Pt(width, min(items, lines)*spacing+2));
66: trc.y = src.y = mrc.y-1;
67: newtop = bound(m->prevtop, 0, items-lines);
68: p = add(mouse.xy, Joffset);
69: p.y -= bound(m->prevhit, 0, lines-1)*spacing+spacing/2;
70: p.x = bound(p.x-(src.x+width/2), Jfscreen.rect.origin.x,
71: Jfscreen.rect.corner.x-mrc.x);
72: p.y = bound(p.y, Jfscreen.rect.origin.y, Jfscreen.rect.corner.y-mrc.y);
73: sr = raddp(sr, p);
74: tr = raddp(tr, p);
75: mr = raddp(mr, p);
76: b = balloc(mr);
77: if(b)
78: bitblt(&Jfscreen, mr, b, mro, F_STORE);
79: rectf(&Jfscreen, mr, F_OR);
80: PaintMenu:
81: rectf(&Jfscreen, inset(mr, 1), F_CLR);
82: top = newtop;
83: if(items > DISPLAY){
84: baro.y = scale(top, 0, items, sro.y, src.y);
85: baro.x = sr.origin.x;
86: barc.y = scale(top+DISPLAY, 0, items, sro.y, src.y);
87: barc.x = sr.corner.x;
88: rectf(&Jfscreen, Rpt(baro,barc), F_XOR);
89: }
90: for(p=tro, i=top; i < min(top+lines, items); ++i){
91: q = p;
92: from = generator(i);
93: for(to = &fill[0]; *from; ++from)
94: if(*from & 0x80)
95: for(j=length-(strlen(from+1)+(to-&fill[0])); j-->0;)
96: *to++ = *from & 0x7F;
97: else
98: *to++ = *from;
99: *to = '\0';
100: q.x += (width-strwidth(font,fill))/2;
101: string(font, fill, &Jfscreen, q, F_XOR);
102: p.y += spacing;
103: }
104: savep = add(mouse.xy, Joffset);
105: for(newhit = hit = -1; button(but); jnap(2)){
106: p = add(mouse.xy, Joffset);
107: if(ptinrect(p, sr)){
108: if(ptinrect(savep,tr)){
109: p.y = (baro.y+barc.y)/2;
110: cursset(sub(p,Joffset));
111: }
112: newtop = scale(p.y, sro.y, src.y, 0, items);
113: newtop = bound(newtop-DISPLAY/2, 0, items-DISPLAY);
114: if(newtop != top)
115: goto PaintMenu;
116: }
117: savep = p;
118: newhit = -1;
119: if(ptinrect(p, tr)){
120: newhit = bound((p.y-tro.y)/spacing, 0, lines-1);
121: if(newhit!=hit && hit>=0
122: && abs(tro.y+spacing*newhit+spacing/2-p.y) > spacing/3)
123: newhit = hit;
124: }
125: if(newhit != hit){
126: flip(tr, hit, spacing);
127: flip(tr, hit = newhit, spacing);
128: }
129: if(newhit==0 && top>0){
130: newtop = top-1;
131: p.y += spacing;
132: cursset(sub(p,Joffset));
133: goto PaintMenu;
134: }
135: if(newhit==DISPLAY-1 && top<items-lines){
136: newtop = top+1;
137: p.y -= spacing;
138: cursset(sub(p,Joffset));
139: goto PaintMenu;
140: }
141: }
142: if(b){
143: bitblt(b, b->rect, &Jfscreen, b->rect.origin, F_STORE);
144: bfree(b);
145: }
146: Jscreenrelease();
147: if(hit>=0){
148: m->prevhit = hit;
149: m->prevtop = top;
150: return hit+top;
151: }else
152: return -1;
153: }
154:
155: static
156: flip(r,n,spacing)
157: Rectangle r;
158: {
159: if(n<0)
160: return;
161: ++r.origin.x;
162: r.corner.y = (r.origin.y += spacing*n) + spacing;
163: --r.corner.x;
164: rectf(&Jfscreen, r, F_XOR);
165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.