This patch is a small change to the saved patch "piemenus-rio". It changes the behaviour of the piemenus, to be no more drawn outside of the screen. Besides this is there a style update, to be more consistent with the "Plan 9 style option int variables" and the style of whole libdraw. Reference: /n/sources/patch/sorry/rio-piemenu-update Date: Tue Aug 9 10:57:30 CES 2005 --- /sys/src/libdraw/piemenuhit.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libdraw/piemenuhit.c Tue Aug 9 10:57:05 2005 @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include + +static Image *back, *bord, *high; + +double +rad(double i) +{ + + return (i * PI) / 180; +} + +double +dist(Point p0, Point p1) +{ + + return sqrt((p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y)); +} + +Point +cente(Point p0, Point p1, Point p2) +{ + double l, d; + Point r0, r1; + + l = dist(p2, p0); + r0.x = p2.x + (((p0.x - p2.x) / l) * l / 2); + r0.y = p2.y + (((p0.y - p2.y) / l) * l / 2); + + l = dist(p1, p0); + r1.x = p1.x + (((p0.x - p1.x) / l) * l / 2); + r1.y = p1.y + (((p0.y - p1.y) / l) * l / 2); + + l = p2.y - r1.y - p1.y + r0.y; + d = (double)(r0.y - r1.y) / l; + + r1.x = r0.x + d * (p1.x - r0.x); + r1.y = r0.y + d * (p1.y - r0.y); + + return r1; +} + +void +draw_pie(Point p, int r, Image *b, Image *w, Image *h, Menu *m, int a, int n) +{ + Point p0, p1; + double d, e, sr; + char *item; + + e = 360 / n; + d = 0; + sr = -1; + + ellipse(screen, p, r, r, 1, h, ZP); + fillellipse(screen, p, r - 1, r - 1, w, ZP); + if(a > 0) + fillarc(screen, p, r, r, b, ZP, (a - 1) * e, e); + + p0 = p; + p1 = p; + + p0.x += cos(rad(d)) * r; + p0.y += sin(rad(d)) * r; + p1.x += cos(rad(d + e)) * r; + p1.y += sin(rad(d + e)) * r; + + sr = dist(cente(p, p0, p1), p); + + d = e / 2; + + while(--n >= 0){ + p0 = p; + item = strdup(m->item[n]); + if(strlen(item) > 8){ + item[8] = '\0'; + item[7] = '.'; + item[6] = '.'; + item[5] = '.'; + } + + p0.x += cos(rad(d)) * sr; + p0.y += sin(rad(d)) * sr; + + p0.x -= stringwidth(font, item) / 2; + p0.y -= font->height / 2; + + string(screen, p0, (n == (a - 1)) ? display->white : display->black, ZP, font, item); + free(item); + d += e; + } + + return; +} + +int +piemenuhit(int but, Mousectl *mc, Menu *menu, Screen *scr) +{ + Rectangle menur; + Image *b, *backup, *back, *high, *bord; + int maxwid, nitem, i, t, set; + double cdeli, cpart, radius; + Point p; + char *item; + + back = allocimagemix(display, DPalegreen, DWhite); + high = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkgreen); + bord = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedgreen); + set = 1; + + if(back == nil || high == nil || bord == nil){ + set = 0; + back = display->white; + high = display->black; + bord = display->black; + } + + replclipr(screen, 0, screen->r); + maxwid = 0; + nitem = 0; + while(item = menu->item ? menu->item[nitem] : (*menu->gen)(nitem)){ + item = strdup(item); + if(strlen(item) > 8) + item[8] = '\0'; + + i = stringwidth(font, item); + if(i > maxwid) + maxwid = i; + free(item); + nitem++; + } + if(menu->lasthit < 0 || menu->lasthit >= nitem) + menu->lasthit = -1; + + p = mc->xy; + radius = ((font->height / 2) + maxwid); + radius += radius * nitem / 8; + if(p.x + radius > screen->r.max.x) + p.x = screen->r.max.x - radius; + if(p.x - radius < screen->r.min.x) + p.x = screen->r.min.x + radius; + if(p.y + radius > screen->r.max.y) + p.y = screen->r.max.y - radius; + if(p.y - radius < screen->r.min.y) + p.y = screen->r.min.y + radius; + moveto(mc, p); + + menur.min = Pt(p.x - radius - 1, p.y - radius - 1); + menur.max = Pt(p.x + radius + 2, p.y + radius + 2); + + cpart = 360 / nitem; + cdeli = cpart / 2; + + if(scr){ + b = allocwindow(scr, menur, Refbackup, DNofill); + if(b == nil) + b = screen; + backup = nil; + }else{ + b = screen; + backup = allocimage(display, Rect(0, 0, Dx(menur), Dy(menur)), screen->chan, 0, DNofill); + if(backup) + draw(backup, backup->r, screen, nil, menur.min); + } + + draw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + + while(mc->buttons & (1<<(but-1))){ + if(dist(p, mc->xy) < radius && dist(p, mc->xy) != 0){ + cdeli = acos((p.x - mc->xy.x) / dist(p, mc->xy)); + if(mc->xy.y >= p.y) + cdeli += rad(180); + if(mc->xy.y < p.y) + cdeli = rad(180) - cdeli; + + i = -1; + t = -1; + while(++t <= nitem){ + if(cdeli < rad(t * cpart) && cdeli <= rad((t + 1) * cpart)){ + i = t; + break; + } + } + + if(i != menu->lasthit || (menu->lasthit == -1 && i != -1)){ + menu->lasthit = i; + draw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + } + } else { + if(menu->lasthit != -1){ + menu->lasthit = -1; + draw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + } + } + readmouse(mc); + } + if(b != screen) + freeimage(b); + if(backup){ + draw(screen, menur, backup, nil, ZP); + freeimage(backup); + } + replclipr(screen, 0, screen->clipr); + flushimage(display, 1); + + if(set){ + freeimage(back); + freeimage(bord); + freeimage(high); + } + + return menu->lasthit - 1; +} --- /sys/src/libdraw/epiemenuhit.c Thu Jan 1 00:00:00 1970 +++ /sys/src/libdraw/epiemenuhit.c Tue Aug 9 10:57:18 2005 @@ -0,0 +1,206 @@ +#include +#include +#include +#include + +static Image *back, *bord, *high; + +double +erad(double i) +{ + + return (i * PI) / 180; +} + +double +edist(Point p0, Point p1) +{ + + return sqrt((p0.x - p1.x) * (p0.x - p1.x) + (p0.y - p1.y) * (p0.y - p1.y)); +} + +Point +ecente(Point p0, Point p1, Point p2) +{ + double l, d; + Point r0, r1; + + l = edist(p2, p0); + r0.x = p2.x + (((p0.x - p2.x) / l) * l / 2); + r0.y = p2.y + (((p0.y - p2.y) / l) * l / 2); + + l = edist(p1, p0); + r1.x = p1.x + (((p0.x - p1.x) / l) * l / 2); + r1.y = p1.y + (((p0.y - p1.x) / l) * l / 2); + + l = p2.x - r1.x - p1.x + r0.x; + d = (double)(r0.x - r1.x) / l; + + r1.x = r0.x + d * (p1.x - r0.x); + r1.y = r0.y + d * (p1.y - r0.y); + + return r1; +} + +void +edraw_pie(Point p, int r, Image *b, Image *w, Image *h, Menu *m, int a, int n) +{ + Point p0, p1; + double d, e, sr; + char *item; + + e = 360 / n; + d = 0; + sr = -1; + + ellipse(screen, p, r, r, 1, h, ZP); + fillellipse(screen, p, r - 1, r - 1, w, ZP); + if(a > 0) + fillarc(screen, p, r, r, b, ZP, (a - 1) * e, e); + + p0 = p; + p1 = p; + + p0.x += cos(erad(d)) * r; + p0.y += sin(erad(d)) * r; + p1.x += cos(erad(d + e)) * r; + p1.y += sin(erad(d + e)) * r; + + sr = edist(ecente(p, p0, p1), p); + + d = e / 2; + + while(--n >= 0){ + p0 = p; + item = strdup(m->item[n]); + if(strlen(item) > 8){ + item[8] = '\0'; + item[7] = '.'; + item[6] = '.'; + item[5] = '.'; + } + + p0.x += cos(erad(d)) * sr; + p0.y += sin(erad(d)) * sr; + + p0.x -= stringwidth(font, item) / 2; + p0.y -= font->height / 2; + + string(screen, p0, (n == (a - 1)) ? display->white : display->black, ZP, font, item); + free(item); + d += e; + } + + return; +} + +int +epiemenuhit(int but, Mouse *m, Menu *menu) +{ + Rectangle menur; + Image *b, *back, *high, *bord; + int maxwid, nitem, i, t; + double cdeli, cpart, radius; + Point p; + char *item, set; + + back = allocimagemix(display, DPalegreen, DWhite); + high = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkgreen); + bord = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedgreen); + set = 1; + + if(back == nil || high == nil || bord == nil){ + set = 0; + back = display->white; + high = display->black; + bord = display->black; + } + + replclipr(screen, 0, screen->r); + maxwid = 0; + nitem = 0; + while(item = menu->item ? menu->item[nitem] : (*menu->gen)(nitem)){ + item = strdup(item); + if(strlen(item) > 8) + item[8] = '\0'; + + i = stringwidth(font, item); + if(i > maxwid) + maxwid = i; + free(item); + nitem++; + } + if(menu->lasthit < 0 || menu->lasthit >= nitem) + menu->lasthit = -1; + + p = m->xy; + radius = ((font->height / 2) + maxwid); + radius += radius * nitem / 8; + if(p.x + radius > screen->r.max.x) + p.x = screen->r.max.x - radius; + if(p.x - radius < screen->r.min.x) + p.x = screen->r.min.x + radius; + if(p.y + radius > screen->r.max.y) + p.y = screen->r.max.y - radius; + if(p.y - radius < screen->r.min.y) + p.y = screen->r.min.y + radius; + emoveto(p); + + menur.min = Pt(p.x - radius - 1, p.y - radius - 1); + menur.max = Pt(p.x + radius + 2, p.y + radius + 2); + + cpart = 360 / nitem; + cdeli = cpart / 2; + + b = allocimage(display, Rect(0, 0, Dx(menur), Dy(menur)), screen->chan, 0, DNofill); + if(b == 0) + b = screen; + draw(b, b->r, screen, nil, menur.min); + + edraw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + + while(m->buttons & (1<<(but-1))){ + if(edist(p, m->xy) < radius && edist(p, m->xy) != 0){ + cdeli = acos((p.x - m->xy.x) / edist(p, m->xy)); + if(m->xy.y >= p.y) + cdeli += erad(180); + if(m->xy.y < p.y) + cdeli = erad(180) - cdeli; + + i = -1; + t = -1; + while(++t <= nitem){ + if(cdeli < erad(t * cpart) && cdeli <= erad((t + 1) * cpart)){ + i = t; + break; + } + } + + if(i != menu->lasthit || (menu->lasthit == -1 && i != -1)){ + menu->lasthit = i; + edraw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + } + } else { + if(menu->lasthit != -1){ + menu->lasthit = -1; + edraw_pie(p, radius, high, back, bord, menu, menu->lasthit, nitem); + } + } + flushimage(display, 1); + *m = emouse(); + } + + draw(screen, menur, b, nil, ZP); + if(b != screen) + freeimage(b); + + replclipr(screen, 0, screen->clipr); + + if(set){ + freeimage(back); + freeimage(bord); + freeimage(high); + } + + return menu->lasthit - 1; +}