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