|
|
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.