|
|
1.1 root 1: #include "jerq.h"
2: #include "menu.h"
3: #define disp Jfscreen
4:
5: #ifdef SUNTOOLS
6: #undef F_STORE
7: #define F_STORE (PIX_DONTCLIP|PIX_SRC)
8: #define F_NCXOR (PIX_DONTCLIP|(PIX_SRC ^ PIX_DST))
9: #else
10: #define F_NCXOR F_XOR
11: #endif SUNTOOLS
12:
13: static screenswap (bp, rect, screenrect)
14: register Bitmap *bp;
15: Rectangle rect;
16: Rectangle screenrect;
17: {
18: bitblt(&disp, screenrect, bp, rect.origin, F_NCXOR);
19: bitblt(bp, rect, &disp, screenrect.origin, F_NCXOR);
20: bitblt(&disp, screenrect, bp, rect.origin, F_NCXOR);
21: }
22:
23: #define scale(x, inmin, inmax, outmin, outmax)\
24: (outmin + muldiv(x-inmin,outmax-outmin,inmax-inmin))
25:
26: #define bound(x, low, high) min(high, max( low, x ))
27:
28: Font *font = &defont;
29: #define SPACING (1+fontheight(font))
30: #define CHARWIDTH fontwidth(font)
31: #define DISPLAY 16
32: #define DELTA 6
33: #define BARWIDTH 18
34: #define MAXDEPTH 16 /* don't use too much stack */
35: #define ARROWIDTH 20
36:
37: static short tarrow_bits[] =
38: {
39: 0x0000, 0x0000, 0x0080, 0x00C0, 0x00C0, 0x00E0, 0x00F8, 0xFFFE,
40: 0xFFFE, 0x00F8, 0x00E0, 0x00C0, 0x00C0, 0x0080, 0x0000, 0x0000,
41: };
42: static Texture tarrow;
43: static int firstime = 1;
44:
45: static NMitem *
46: tablegen(i, table)
47: NMitem *table;
48: {
49: return &table[i];
50: }
51:
52: static char fill[64];
53:
54: NMitem *
55: mhit(m, but, depth)
56: register NMenu *m;
57: {
58: register int width, mwidth, i, j, top, newtop, hit, newhit;
59: register int items, lines, length, w, x;
60: Point p, q, savep, baro, barc;
61: Rectangle sr, tr, mr; /* scroll, text, menu */
62: Rectangle rside, rhit;
63: register Bitmap *b;
64: register char *from, *to;
65: Bitmap *bhelp = 0, *arrow;
66: NMitem *(*generator)(), *mi, *table, *ret = 0;
67: int dohfn;
68:
69: #define sro sr.origin
70: #define src sr.corner
71: #define tro tr.origin
72: #define trc tr.corner
73: #define mro mr.origin
74: #define mrc mr.corner
75:
76: if (firstime) {
77: firstime = 0;
78: tarrow = ToTexture(tarrow_bits);
79: }
80: generator = (table=m->item) ? tablegen : m->generator;
81: arrow = balloc(Rect(0, 0, 16, 16));
82: texture(arrow, arrow->rect, &tarrow, F_STORE);
83: w = x = length = 0;
84: for(items = 0; (mi=(*generator)(items, table))->text; ++items) {
85: register int s = strlen (mi->text);
86: length = max(length, s);
87: if (mi->next) {
88: w = max (w, s);
89: } else
90: x = max (x, s);
91: }
92: if(items == 0)
93: return(ret);
94: Jscreengrab();
95: width = length*CHARWIDTH+10;
96: w *= CHARWIDTH;
97: x *= CHARWIDTH;
98: if (x <= w)
99: mwidth = w + ARROWIDTH;
100: else if (x >= w + 2*ARROWIDTH)
101: mwidth = x;
102: else
103: mwidth = w + ARROWIDTH + (x - w) / 2;
104: mwidth += 10;
105: sro.x = sro.y = src.x = tro.x = mro.x = mro.y = 0;
106: if(items <= DISPLAY)
107: lines = items;
108: else{
109: lines = DISPLAY;
110: tro.x = src.x = BARWIDTH;
111: sro.x = sro.y = 1;
112: }
113: #define ASCEND 2
114: tro.y = ASCEND;
115: mrc = trc = add(tro, Pt(mwidth, min(items, lines)*SPACING));
116: src.y = mrc.y-1;
117: newtop = bound(m->prevtop, 0, items-lines);
118: p = add(mouse.xy, Joffset);
119: p.y -= bound(m->prevhit, 0, lines-1)*SPACING+SPACING/2;
120: p.x = bound(p.x-(src.x+mwidth/2), Jfscreen.rect.origin.x,
121: Jfscreen.rect.corner.x-mrc.x);
122: p.y = bound(p.y, Jfscreen.rect.origin.y, Jfscreen.rect.corner.y-mrc.y);
123: sr = raddp(sr, p);
124: tr = raddp(tr, p);
125: mr = raddp(mr, p);
126: rside = mr;
127: rside.origin.x = rside.corner.x-20;
128: b = balloc(mr);
129: cursinhibit();
130: if(b)
131: bitblt(&disp, mr, b, mro, F_STORE);
132: rectf(&disp, mr, F_OR);
133: cursallow();
134: PaintMenu:
135: cursinhibit();
136: rectf(&disp, inset(mr, 1), F_CLR);
137: cursallow();
138: top = newtop;
139: if(items > DISPLAY){
140: baro.y = scale(top, 0, items, sro.y, src.y);
141: baro.x = sr.origin.x;
142: barc.y = scale(top+DISPLAY, 0, items, sro.y, src.y);
143: barc.x = sr.corner.x;
144: rectf(&disp, Rpt(baro,barc), F_XOR);
145: }
146: for(p=tro, i=top; i < min(top+lines, items); ++i){
147: q = p;
148: mi = generator(i, table);
149: from = mi->text;
150: for(to = &fill[0]; *from; ++from)
151: if(*from & 0x80)
152: for(j=length-(strlen(from+1)+(to-&fill[0])); j-->0;)
153: *to++ = *from & 0x7F;
154: else
155: *to++ = *from;
156: *to = '\0';
157: q.x += (width-strwidth(font,fill))/2;
158: string(&defont, fill, &disp, q, F_XOR);
159: if(mi->next)
160: bitblt(arrow, arrow->rect, &disp, Pt(trc.x-18, p.y-2), F_OR);
161: p.y += SPACING;
162: }
163: savep = add(mouse.xy, Joffset);
164: mi = 0;
165: for(newhit = hit = -1; button(but); ){
166: p = add(mouse.xy, Joffset);
167: if(depth && ((p.x < mro.x) || button(5-but)))
168: {
169: ret = 0;
170: break;
171: }
172: if(ptinrect(p, sr)){
173: if(ptinrect(savep,tr)){
174: p.y = (baro.y+barc.y)/2;
175: cursset(sub(p,Joffset));
176: }
177: newtop = scale(p.y, sro.y, src.y, 0, items);
178: newtop = bound(newtop-DISPLAY/2, 0, items-DISPLAY);
179: if(newtop != top)
180: /* ->->-> */ goto PaintMenu;
181: }else if(ptinrect(savep,sr)){
182: register dx, dy;
183: if(abs(dx = p.x-savep.x) < DELTA)
184: dx = 0;
185: if(abs(dy = p.y-savep.y) < DELTA)
186: dy = 0;
187: if(abs(dy) >= abs(dx))
188: dx = 0;
189: else
190: dy = 0;
191: p = add(savep, Pt(dx,dy));
192: cursset(sub(p,Joffset));
193: }
194: savep = p;
195: newhit = -1;
196: if(ptinrect(p, tr)){
197: newhit = bound((p.y-tro.y)/SPACING, 0, lines-1);
198: if(newhit!=hit && hit>=0
199: && abs(tro.y+SPACING*newhit+SPACING/2-p.y) > SPACING/3)
200: newhit = hit;
201: rhit = tr;
202: rhit.origin.y += newhit*SPACING-ASCEND/2;
203: rhit.corner.y = rhit.origin.y + SPACING;
204: }
205: if(newhit == -1)
206: ret = 0, dohfn = 0;
207: else
208: ret = mi = (*generator)(top+newhit, table), dohfn = 1;
209: if(newhit == hit)
210: {
211: if((newhit != -1) && (bhelp == 0) && button1() && mi->help)
212: helpon(mi->help, rhit, &bhelp);
213: else if(bhelp && !button1())
214: helpoff(&bhelp);
215: }
216: else
217: {
218: flip(tr, hit);
219: helpoff(&bhelp);
220: flip(tr, newhit);
221: hit = newhit;
222: if((newhit != -1) && button1() && mi->help)
223: helpon(mi->help, rhit, &bhelp);
224: }
225: if((newhit != -1) && ptinrect(p, rside))
226: {
227: if(mi->dfn) (*mi->dfn)(mi);
228: if(mi->next && (depth <= MAXDEPTH))
229: ret = mhit(mi->next, but, depth+1), dohfn = 0;
230: if(mi->bfn) (*mi->bfn)(mi);
231: }
232: if(newhit==0 && top>0){
233: newtop = top-1;
234: p.y += SPACING;
235: cursset(sub(p,Joffset));
236: /* ->->-> */ goto PaintMenu;
237: }
238: if(newhit==DISPLAY-1 && top<items-lines){
239: newtop = top+1;
240: p.y -= SPACING;
241: cursset(sub(p,Joffset));
242: /* ->->-> */ goto PaintMenu;
243: }
244: if (button(but))
245: nap(2);
246: }
247: if(bhelp)
248: helpoff(&bhelp);
249: if(b){
250: cursinhibit();
251: screenswap(b, b->rect, b->rect);
252: cursallow();
253: bfree(b);
254: }
255: if(hit>=0){
256: m->prevhit = hit;
257: m->prevtop = top;
258: if(ret && ret->hfn && dohfn) (*ret->hfn)(mi);
259: }
260: Jscreenrelease();
261: return(ret);
262: }
263:
264: static
265: flip(r,n)
266: Rectangle r;
267: {
268: if(n<0)
269: return;
270: ++r.origin.x;
271: r.corner.y = (r.origin.y += SPACING*n-1) + SPACING;
272: --r.corner.x;
273: rectf(&disp, r, F_XOR);
274: }
275:
276: static
277: helpon(msg, r, bhelp)
278: char *msg;
279: Rectangle r;
280: Bitmap **bhelp;
281: {
282: register Bitmap *b;
283: register w;
284:
285: w = strwidth(&defont, msg)+10;
286: if(r.corner.x+w < disp.rect.corner.x){
287: r.origin.x = r.corner.x;
288: r.corner.x += w;
289: }
290: else{
291: r.corner.x = r.origin.x;
292: r.origin.x -= w;
293: }
294: if(*bhelp = b = balloc(r = inset(r, -1))){
295: rectf(b, r, F_OR);
296: rectf(b, inset(r, 1), F_XOR);
297: string(&defont, msg, b, add(b->rect.origin, Pt(5, 1)),F_XOR);
298: screenswap(b, b->rect, b->rect);
299: }
300: }
301:
302: static
303: helpoff (bhelp)
304: Bitmap **bhelp;
305: {
306: Bitmap *bh;
307:
308: if(bh = *bhelp){
309: screenswap(bh, bh->rect, bh->rect);
310: bfree(bh);
311: *bhelp = 0;
312: }
313: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.