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