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