#include "art.h" Image *darkgrey, *black, *background, *menucolor; char *mslopes[], *mparallels[], *mcircles[], *mangles[], *mgrid[], *mgravity[], *mheating[]; char **menubar[]={ mslopes, mangles, mparallels, mcircles, mgrid, mgravity, mheating, 0 }; int hitmenubar(void){ int hit=mbarhit(&mouse); if(hit==-1) return -1; switch(hit/100){ /* get y co-ordinate of the mouse as row number */ case 0: Oslope(hit%100); break; case 1: Oangle(hit%100); break; case 2: Oparallel(hit%100); break; case 3: Ocirc(hit%100); break; case 4: Ogrid(hit%100); break; case 5: Ogravity(hit%100); break; case 6: Oheating(hit%100); break; } return hit; } Rectangle drawmenubar(void){ return mbarinit(menubar); } /* * Menu bar library routines. * * Rectangle mbarinit(char **menubar[]) * draws a menu bar on the screen, returns a rectangle covering the free * part of the screen (not in the menu bar and not in the 8-1/2 border). * Must be called before to * The argument is an array of pointers, one per menu, to arrays of strings. * The first element of each string array is a name to display on the menu bar. * The remaining elements are the menu items. * All arrays end at zero pointers. * * int mbarhit(Mouse *m) * returns a button indicator (100*col+row), where menubar[col][row+1] is the button * hit, or -1 on no hit. * The argument initially points to a mouse event that should have some button down. * It is updated to be the event that caused mbarhit to return. If m->buttons * is non-zero on return, then m->xy was not inside the menu bar on entry. (In this * case, m has not changed and mbarhit returns -1.) */ #define BORDER 1 /* width of 8+1/2 border */ #define SPACE 10 /* inter-button spacing on menu bar */ static Rectangle bar; /* encloses menu bar */ static char ***buttons; Rectangle mbarinit(char **menubar[]){ int i; Point p; buttons=menubar; bar.min=addpt(screen->r.min, Pt(BORDER, BORDER)); bar.max.x=screen->r.max.x-BORDER; bar.max.y=screen->r.min.y+BORDER+4+font->height; draw(screen, bar, menucolor, 0, ZP); /* set the color of menubar */ border(screen, bar, 1, darkgrey, ZP); p=addpt(bar.min, Pt(2+SPACE/2, 2)); for(i=0;buttons[i];i++){ string(screen, p, black, Pt(0,0), font, buttons[i][0]); p.x+=stringwidth(font, buttons[i][0])+SPACE; } return Rect(bar.min.x, bar.max.y, bar.max.x, screen->r.max.y-BORDER); } int mbarhit(Mouse *m){ Image *save=0; /* screen under menu is saved here */ Rectangle colcom; /* menu bar is complemented under this rectangle */ int col=-1; /* index of currently visible menu */ Rectangle rowcom; /* menu is complemented under this rectangle */ int row=-1; /* index of currently visible menu item */ int nmenu; /* number of rows in currently visible menu */ int i, j, right; Rectangle r; Point p; if(!m->buttons || !ptinrect(m->xy, bar)) return -1; for(;m->buttons;*m=emouse()){ if(save && ptinrect(m->xy, save->r)){ if(m->xy.yr.min.y+1) j=0; else{ j=(m->xy.y-save->r.min.y-1)/(font->height+2); /* j = number of rows */ if(nmenu<=j) j=nmenu-1; } if(row==j) continue; if(row>=0) draw(screen, rowcom, background, 0, rowcom.min); row=j; rowcom.min.x=save->r.min.x+1; rowcom.max.x=save->r.max.x-1; rowcom.min.y=save->r.min.y+1+row*(2+font->height); rowcom.max.y=rowcom.min.y+2+font->height; draw(screen, rowcom, screen, 0, rowcom.min); } else{ if(row>=0){ draw(screen, rowcom, screen, 0, rowcom.min); row=-1; } if(!ptinrect(m->xy, bar)) continue; r.min.y=bar.min.y; r.max.y=bar.max.y; r.max.x=bar.min.x+SPACE/2; for(i=0;buttons[i];i++){ r.min.x=r.max.x; r.max.x+=stringwidth(font, buttons[i][0])+SPACE; if(ptinrect(m->xy, r)) break; } if(!buttons[i]) i=-1; if(i==col) continue; col=i; if(save){ draw(screen, save->r, save, 0, save->r.min); draw(screen, colcom, screen, 0, colcom.min); freeimage(save); save=0; } if(i==-1) continue; colcom=r; r.min=Pt(colcom.min.x, colcom.max.y-1); r.max=addpt(r.min, Pt(4, 2)); colcom.min.y++; --colcom.max.y; for(j=1;buttons[i][j];j++){ right=stringwidth(font, buttons[i][j])+4+r.min.x; if(r.max.xheight+2; } save=allocimage(display, r, chan, 1, DPaleblue); if(!save) break; draw(screen, colcom, screen, 0, colcom.min); draw(save, r, screen, 0, r.min); draw(screen, r, screen, 0, r.min); border(screen, r, 1, darkgrey, ZP); p=addpt(r.min, Pt(2, 2)); for(j=1;buttons[i][j];j++){ string(screen, p, black, Pt(0, 0), font, buttons[i][j]); p.y+=2+font->height; } nmenu=j-1; } } if(save){ draw(screen, save->r, save, 0, save->r.min); draw(screen, colcom, screen, 0, colcom.min); freeimage(save); } return col>=0 && row>=0?col*100+row:-1; }