ref: b85e023d0fb10b704d116742bfaf251ceca42ca9
parent: 14cac15cc44e62351d644e8fb31dc600fa25ee14
author: qwx <qwx@sciops.net>
date: Wed Jan 7 05:32:46 EST 2026
libdraw: sync with 9front
--- a/sys/src/libdraw/eenter.c
+++ /dev/null
@@ -1,241 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-#include <keyboard.h>
-
-int
-eenter(char *ask, char *buf, int len, Mouse *m)
-{- int done, down, tick, n, h, w, l, i;
- Image *b, *save, *backcol, *bordcol, *txtcol;
- Point p, o, t;
- Rectangle r, sc;
- Event ev;
- Rune k;
-
- o = screen->r.min;
-
- enum{- Cback,
- Cbord,
- Ctext,
- Ncols,
- };
- Theme th[Ncols] = {- [Cback] { "menuback", 0xEAFFEAFF },- [Cbord] { "menubord", DMedgreen },- [Ctext] { "menutext", DBlack },- };
- readtheme(th, nelem(th), nil);
- backcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
- bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
- txtcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
- if(backcol == nil || bordcol == nil || txtcol == nil)
- return -1;
-
- while(ecankbd())
- ekbd();
-
- if(m) o = m->xy;
-
- if(buf && len > 0)
- n = strlen(buf);
- else {- buf = nil;
- len = 0;
- n = 0;
- }
-
- k = -1;
- tick = n;
- save = nil;
- done = down = 0;
-
- p = stringsize(font, " ");
- h = p.y;
- w = p.x;
-
- b = screen;
- sc = b->clipr;
- replclipr(b, 0, b->r);
-
- while(!done){- p = stringsize(font, buf ? buf : "");
- if(ask && ask[0]){- if(buf) p.x += w;
- p.x += stringwidth(font, ask);
- }
- r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
- p.x = 0;
- r = rectsubpt(r, p);
-
- p = ZP;
- if(r.min.x < screen->r.min.x)
- p.x = screen->r.min.x - r.min.x;
- if(r.min.y < screen->r.min.y)
- p.y = screen->r.min.y - r.min.y;
- r = rectaddpt(r, p);
- p = ZP;
- if(r.max.x > screen->r.max.x)
- p.x = r.max.x - screen->r.max.x;
- if(r.max.y > screen->r.max.y)
- p.y = r.max.y - screen->r.max.y;
- r = rectsubpt(r, p);
-
- r = insetrect(r, -2);
- if(save == nil){- save = allocimage(display, r, b->chan, 0, DNofill);
- if(save == nil){- n = -1;
- break;
- }
- draw(save, r, b, nil, r.min);
- }
- draw(b, r, backcol, nil, ZP);
- border(b, r, 2, bordcol, ZP);
- p = addpt(r.min, Pt(6, 6));
- if(ask && ask[0]){- p = string(b, p, bordcol, ZP, font, ask);
- if(buf) p.x += w;
- }
- if(buf){- t = p;
- p = stringn(b, p, txtcol, ZP, font, buf, utfnlen(buf, tick));
- draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), txtcol, nil, ZP);
- draw(b, Rect(p.x, p.y, p.x+1, p.y+h), txtcol, nil, ZP);
- draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), txtcol, nil, ZP);
- p = string(b, p, txtcol, ZP, font, buf+tick);
- }
- flushimage(display, 1);
-
-nodraw:
- i = Ekeyboard;
- if(m != nil)
- i |= Emouse;
-
- replclipr(b, 0, sc);
- i = eread(i, &ev);
-
- /* screen might have been resized */
- if(b != screen || !eqrect(screen->clipr, sc)){- freeimage(save);
- save = nil;
- }
- b = screen;
- sc = b->clipr;
- replclipr(b, 0, b->r);
-
- switch(i){- default:
- done = 1;
- n = -1;
- break;
- case Ekeyboard:
- k = ev.kbdc;
- if(buf == nil || k == Keof || k == '\n'){- done = 1;
- break;
- }
- if(k == Knack || k == Kesc){- done = !n;
- buf[n = tick = 0] = 0;
- break;
- }
- if(k == Ksoh || k == Khome){- tick = 0;
- continue;
- }
- if(k == Kenq || k == Kend){- tick = n;
- continue;
- }
- if(k == Kright){- if(tick < n)
- tick += chartorune(&k, buf+tick);
- continue;
- }
- if(k == Kleft){- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- if(i+l >= tick){- tick = i;
- break;
- }
- }
- continue;
- }
- if(k == Ketb){- l = tick;
- while(tick > 0){- tick--;
- if(tick == 0 ||
- strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))- break;
- }
- memmove(buf+tick, buf+l, n-l);
- buf[n -= l-tick] = 0;
- break;
- }
- if(k == Kbs){- if(tick <= 0)
- continue;
- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- if(i+l >= tick){- memmove(buf+i, buf+i+l, n - (i+l));
- buf[n -= l] = 0;
- tick -= l;
- break;
- }
- }
- break;
- }
- if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
- continue;
- if((len-n) <= (l = runelen(k)))
- continue;
- memmove(buf+tick+l, buf+tick, n - tick);
- runetochar(buf+tick, &k);
- buf[n += l] = 0;
- tick += l;
- break;
- case Emouse:
- *m = ev.mouse;
- if(!ptinrect(m->xy, r)){- down = 0;
- goto nodraw;
- }
- if(m->buttons & 7){- down = 1;
- if(buf && m->xy.x >= (t.x - w)){- down = 0;
- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- t.x += stringnwidth(font, buf+i, 1);
- if(t.x > m->xy.x)
- break;
- }
- tick = i;
- }
- continue;
- }
- done = down;
- break;
- }
- if(save){- draw(b, save->r, save, nil, save->r.min);
- freeimage(save);
- save = nil;
- }
- }
-
- replclipr(b, 0, sc);
-
- freeimage(backcol);
- freeimage(bordcol);
- flushimage(display, 1);
-
- return n;
-}
-
--- a/sys/src/libdraw/emenuhit.c
+++ /dev/null
@@ -1,291 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <event.h>
-
-enum
-{- Margin = 4, /* outside to text */
- Border = 2, /* outside to selection boxes */
- Blackborder = 2, /* width of outlining border */
- Vspacing = 2, /* extra spacing between lines of text */
- Maxunscroll = 25, /* maximum #entries before scrolling turns on */
- Nscroll = 20, /* number entries in scrolling part */
- Scrollwid = 14, /* width of scroll bar */
- Gap = 4, /* between text and scroll bar */
-};
-
-static Image *menutxt;
-static Image *back;
-static Image *high;
-static Image *bord;
-static Image *text;
-static Image *htext;
-
-static
-void
-menucolors(void)
-{- enum{- Cback,
- Chigh,
- Cbord,
- Ctext,
- Chtext,
- Cmtext,
- Ncols,
- };
- Theme th[Ncols] = {- [Cback] { "menuback", 0xEAFFEAFF },- [Chigh] { "menuhigh", DDarkgreen },- [Cbord] { "menubord", DMedgreen },- [Ctext] { "menutext", DBlack },- [Chtext]{ "menuhtext", 0xEAFFEAFF },- [Cmtext]{ "menubar", DDarkgreen },- };
-
- readtheme(th, nelem(th), nil);
- back = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
- high = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chigh].c);
- bord = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
- text = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
- htext = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chtext].c);
- menutxt = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cmtext].c);
- if(back == nil || high == nil || bord == nil
- || text == nil || htext == nil || menutxt == nil)
- goto Error;
- return;
-
- Error:
- freeimage(back);
- freeimage(high);
- freeimage(bord);
- freeimage(menutxt);
- freeimage(htext);
- freeimage(text);
- back = display->white;
- high = display->black;
- bord = display->black;
- text = display->black;
- htext = display->white;
- menutxt = display->black;
-}
-
-/*
- * r is a rectangle holding the text elements.
- * return the rectangle, including its black edge, holding element i.
- */
-static Rectangle
-menurect(Rectangle r, int i)
-{- if(i < 0)
- return Rect(0, 0, 0, 0);
- r.min.y += (font->height+Vspacing)*i;
- r.max.y = r.min.y+font->height+Vspacing;
- return insetrect(r, Border-Margin);
-}
-
-/*
- * r is a rectangle holding the text elements.
- * return the element number containing p.
- */
-static int
-menusel(Rectangle r, Point p)
-{- if(!ptinrect(p, r))
- return -1;
- return (p.y-r.min.y)/(font->height+Vspacing);
-}
-
-static
-void
-paintitem(Menu *menu, Rectangle textr, int off, int i, int highlight, Image *save, Image *restore)
-{- char *item;
- Rectangle r;
- Point pt;
-
- if(i < 0)
- return;
- r = menurect(textr, i);
- if(restore){- draw(screen, r, restore, nil, restore->r.min);
- return;
- }
- if(save)
- draw(save, save->r, screen, nil, r.min);
- item = menu->item? menu->item[i+off] : (*menu->gen)(i+off);
- pt.x = (textr.min.x+textr.max.x-stringwidth(font, item))/2;
- pt.y = textr.min.y+i*(font->height+Vspacing);
- draw(screen, r, highlight? high : back, nil, pt);
- string(screen, pt, highlight? htext : text, pt, font, item);
-}
-
-/*
- * menur is a rectangle holding all the highlightable text elements.
- * track mouse while inside the box, return what's selected when button
- * is raised, -1 as soon as it leaves box.
- * invariant: nothing is highlighted on entry or exit.
- */
-static int
-menuscan(Menu *menu, int but, Mouse *m, Rectangle textr, int off, int lasti, Image *save)
-{- int i;
-
- paintitem(menu, textr, off, lasti, 1, save, nil);
- flushimage(display, 1);
- *m = emouse();
- while(m->buttons & (1<<(but-1))){- flushimage(display, 1);
- *m = emouse();
- i = menusel(textr, m->xy);
- if(i != -1 && i == lasti)
- continue;
- paintitem(menu, textr, off, lasti, 0, nil, save);
- if(i == -1)
- return i;
- lasti = i;
- paintitem(menu, textr, off, lasti, 1, save, nil);
- }
- return lasti;
-}
-
-static void
-menupaint(Menu *menu, Rectangle textr, int off, int nitemdrawn)
-{- int i;
-
- draw(screen, insetrect(textr, Border-Margin), back, nil, ZP);
- for(i = 0; i<nitemdrawn; i++)
- paintitem(menu, textr, off, i, 0, nil, nil);
-}
-
-static void
-menuscrollpaint(Rectangle scrollr, int off, int nitem, int nitemdrawn)
-{- Rectangle r;
-
- draw(screen, scrollr, back, nil, ZP);
- r.min.x = scrollr.min.x;
- r.max.x = scrollr.max.x;
- r.min.y = scrollr.min.y + (Dy(scrollr)*off)/nitem;
- r.max.y = scrollr.min.y + (Dy(scrollr)*(off+nitemdrawn))/nitem;
- if(r.max.y < r.min.y+2)
- r.max.y = r.min.y+2;
- border(screen, r, 1, bord, ZP);
- draw(screen, insetrect(r, 1), menutxt, nil, ZP);
-}
-
-int
-emenuhit(int but, Mouse *m, Menu *menu)
-{- int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem;
- int scrolling;
- Rectangle r, menur, sc, textr, scrollr;
- Image *b, *save;
- Point pt;
- char *item;
-
- if(back == nil)
- menucolors();
- sc = screen->clipr;
- replclipr(screen, 0, screen->r);
- maxwid = 0;
- for(nitem = 0;
- item = menu->item? menu->item[nitem] : (*menu->gen)(nitem);
- nitem++){- i = stringwidth(font, item);
- if(i > maxwid)
- maxwid = i;
- }
- if(menu->lasthit<0 || menu->lasthit>=nitem)
- menu->lasthit = 0;
- screenitem = (Dy(screen->r)-10)/(font->height+Vspacing);
- if(nitem>Maxunscroll || nitem>screenitem){- scrolling = 1;
- nitemdrawn = Nscroll;
- if(nitemdrawn > screenitem)
- nitemdrawn = screenitem;
- wid = maxwid + Gap + Scrollwid;
- off = menu->lasthit - nitemdrawn/2;
- if(off < 0)
- off = 0;
- if(off > nitem-nitemdrawn)
- off = nitem-nitemdrawn;
- lasti = menu->lasthit-off;
- }else{- scrolling = 0;
- nitemdrawn = nitem;
- wid = maxwid;
- off = 0;
- lasti = menu->lasthit;
- }
- r = insetrect(Rect(0, 0, wid, nitemdrawn*(font->height+Vspacing)), -Margin);
- r = rectsubpt(r, Pt(wid/2, lasti*(font->height+Vspacing)+font->height/2));
- r = rectaddpt(r, m->xy);
- pt = ZP;
- if(r.max.x>screen->r.max.x)
- pt.x = screen->r.max.x-r.max.x;
- if(r.max.y>screen->r.max.y)
- pt.y = screen->r.max.y-r.max.y;
- if(r.min.x<screen->r.min.x)
- pt.x = screen->r.min.x-r.min.x;
- if(r.min.y<screen->r.min.y)
- pt.y = screen->r.min.y-r.min.y;
- menur = rectaddpt(r, pt);
- textr.max.x = menur.max.x-Margin;
- textr.min.x = textr.max.x-maxwid;
- textr.min.y = menur.min.y+Margin;
- textr.max.y = textr.min.y + nitemdrawn*(font->height+Vspacing);
- if(scrolling){- scrollr = insetrect(menur, Border);
- scrollr.max.x = scrollr.min.x+Scrollwid;
- }else
- scrollr = Rect(0, 0, 0, 0);
-
- b = allocimage(display, menur, screen->chan, 0, 0);
- if(b == 0)
- b = screen;
- draw(b, menur, screen, nil, menur.min);
- draw(screen, menur, back, nil, ZP);
- border(screen, menur, Blackborder, bord, ZP);
- save = allocimage(display, menurect(textr, 0), screen->chan, 0, -1);
- r = menurect(textr, lasti);
- if(pt.x || pt.y)
- emoveto(divpt(addpt(r.min, r.max), 2));
- menupaint(menu, textr, off, nitemdrawn);
- if(scrolling)
- menuscrollpaint(scrollr, off, nitem, nitemdrawn);
- while(m->buttons & (1<<(but-1))){- lasti = menuscan(menu, but, m, textr, off, lasti, save);
- if(lasti >= 0)
- break;
- while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){- if(scrolling && ptinrect(m->xy, scrollr)){- noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scrollr);
- noff -= nitemdrawn/2;
- if(noff < 0)
- noff = 0;
- if(noff > nitem-nitemdrawn)
- noff = nitem-nitemdrawn;
- if(noff != off){- off = noff;
- menupaint(menu, textr, off, nitemdrawn);
- menuscrollpaint(scrollr, off, nitem, nitemdrawn);
- }
- }
- flushimage(display, 1);
- *m = emouse();
- }
- }
- draw(screen, menur, b, nil, menur.min);
- if(b != screen)
- freeimage(b);
- freeimage(save);
- replclipr(screen, 0, sc);
- if(lasti >= 0){- menu->lasthit = lasti+off;
- return menu->lasthit;
- }
- return -1;
-}
--- a/sys/src/libdraw/enter.c
+++ /dev/null
@@ -1,251 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <mouse.h>
-#include <keyboard.h>
-
-int
-enter(char *ask, char *buf, int len, Mousectl *mc, Keyboardctl *kc, Screen *scr)
-{- int done, down, tick, n, h, w, l, i;
- Image *b, *save, *backcol, *bordcol, *txtcol;
- Point p, o, t;
- Rectangle r, sc;
- Alt a[3];
- Mouse m;
- Rune k;
-
- o = screen->r.min;
-
- enum{- Cback,
- Cbord,
- Ctext,
- Ncols,
- };
- Theme th[Ncols] = {- [Cback] { "menuback", 0xEAFFEAFF },- [Cbord] { "menubord", DMedgreen },- [Ctext] { "menutext", DBlack },- };
- readtheme(th, nelem(th), nil);
- backcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
- bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
- txtcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
- if(backcol == nil || bordcol == nil || txtcol == nil)
- return -1;
-
- sc = screen->clipr;
- replclipr(screen, 0, screen->r);
-
- n = 0;
- if(kc){- while(nbrecv(kc->c, nil) == 1)
- ;
- a[n].op = CHANRCV;
- a[n].c = kc->c;
- a[n].v = &k;
- n++;
- }
- if(mc){- o = mc->xy;
- a[n].op = CHANRCV;
- a[n].c = mc->c;
- a[n].v = &m;
- n++;
- }
- a[n].op = CHANEND;
- a[n].c = nil;
- a[n].v = nil;
-
- if(buf && len > 0)
- n = strlen(buf);
- else {- buf = nil;
- len = 0;
- n = 0;
- }
-
- k = -1;
- b = nil;
- tick = n;
- save = nil;
- done = down = 0;
-
- p = stringsize(font, " ");
- h = p.y;
- w = p.x;
-
- while(!done){- p = stringsize(font, buf ? buf : "");
- if(ask && ask[0]){- if(buf) p.x += w;
- p.x += stringwidth(font, ask);
- }
- r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
- p.x = 0;
- r = rectsubpt(r, p);
-
- p = ZP;
- if(r.min.x < screen->r.min.x)
- p.x = screen->r.min.x - r.min.x;
- if(r.min.y < screen->r.min.y)
- p.y = screen->r.min.y - r.min.y;
- r = rectaddpt(r, p);
- p = ZP;
- if(r.max.x > screen->r.max.x)
- p.x = r.max.x - screen->r.max.x;
- if(r.max.y > screen->r.max.y)
- p.y = r.max.y - screen->r.max.y;
- r = rectsubpt(r, p);
-
- r = insetrect(r, -2);
- if(scr){- if(b == nil)
- b = allocwindow(scr, r, Refbackup, DWhite);
- if(b == nil)
- scr = nil;
- }
- if(scr == nil && save == nil){- if(b == nil)
- b = screen;
- save = allocimage(display, r, b->chan, 0, DNofill);
- if(save == nil){- n = -1;
- break;
- }
- draw(save, r, b, nil, r.min);
- }
- draw(b, r, backcol, nil, ZP);
- border(b, r, 2, bordcol, ZP);
- p = addpt(r.min, Pt(6, 6));
- if(ask && ask[0]){- p = string(b, p, bordcol, ZP, font, ask);
- if(buf) p.x += w;
- }
- if(buf){- t = p;
- p = stringn(b, p, txtcol, ZP, font, buf, utfnlen(buf, tick));
- draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), txtcol, nil, ZP);
- draw(b, Rect(p.x, p.y, p.x+1, p.y+h), txtcol, nil, ZP);
- draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), txtcol, nil, ZP);
- p = string(b, p, txtcol, ZP, font, buf+tick);
- }
- flushimage(display, 1);
-
-nodraw:
- switch(alt(a)){- case -1:
- done = 1;
- n = -1;
- break;
- case 0:
- if(buf == nil || k == Keof || k == '\n'){- done = 1;
- break;
- }
- if(k == Knack || k == Kesc){- done = !n;
- buf[n = tick = 0] = 0;
- break;
- }
- if(k == Ksoh || k == Khome){- tick = 0;
- continue;
- }
- if(k == Kenq || k == Kend){- tick = n;
- continue;
- }
- if(k == Kright){- if(tick < n)
- tick += chartorune(&k, buf+tick);
- continue;
- }
- if(k == Kleft){- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- if(i+l >= tick){- tick = i;
- break;
- }
- }
- continue;
- }
- if(k == Ketb){- l = tick;
- while(tick > 0){- tick--;
- if(tick == 0 ||
- strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))- break;
- }
- memmove(buf+tick, buf+l, n-l);
- buf[n -= l-tick] = 0;
- break;
- }
- if(k == Kbs){- if(tick <= 0)
- continue;
- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- if(i+l >= tick){- memmove(buf+i, buf+i+l, n - (i+l));
- buf[n -= l] = 0;
- tick -= l;
- break;
- }
- }
- break;
- }
- if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
- continue;
- if((len-n) <= (l = runelen(k)))
- continue;
- memmove(buf+tick+l, buf+tick, n - tick);
- runetochar(buf+tick, &k);
- buf[n += l] = 0;
- tick += l;
- break;
- case 1:
- if(!ptinrect(m.xy, r)){- down = 0;
- goto nodraw;
- }
- if(m.buttons & 7){- down = 1;
- if(buf && m.xy.x >= (t.x - w)){- down = 0;
- for(i = 0; i < n; i += l){- l = chartorune(&k, buf+i);
- t.x += stringnwidth(font, buf+i, 1);
- if(t.x > m.xy.x)
- break;
- }
- tick = i;
- }
- continue;
- }
- done = down;
- break;
- }
-
- if(b != screen) {- freeimage(b);
- b = nil;
- } else {- draw(b, save->r, save, nil, save->r.min);
- freeimage(save);
- save = nil;
- }
- }
-
- replclipr(screen, 0, sc);
-
- freeimage(backcol);
- freeimage(bordcol);
- flushimage(display, 1);
-
- return n;
-}
--- /dev/null
+++ b/sys/src/libdraw/genenter.c
@@ -1,0 +1,227 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+
+int
+genenter(char *ask, char *buf, int len, Mouse *m, void *c, int (*_input)(Mouse*, void*, Rune*), Screen *scr)
+{+ int done, down, tick, n, h, w, l, i;
+ Image *b, *save, *backcol, *bordcol, *txtcol;
+ Point p, o, t;
+ Rectangle r, sc;
+ Rune k;
+
+ enum{+ Cback,
+ Cbord,
+ Ctext,
+ Ncols,
+ };
+ Theme th[Ncols] = {+ [Cback] { "menuback", 0xEAFFEAFF },+ [Cbord] { "menubord", DMedgreen },+ [Ctext] { "menutext", DBlack },+ };
+ readtheme(th, nelem(th), nil);
+ backcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
+ bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
+ txtcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
+ if(backcol == nil || bordcol == nil || txtcol == nil)
+ return -1;
+
+ sc = screen->clipr;
+ replclipr(screen, 0, screen->r);
+
+ if(buf && len > 0)
+ n = strlen(buf);
+ else {+ buf = nil;
+ len = 0;
+ n = 0;
+ }
+
+ k = -1;
+ b = nil;
+ tick = n;
+ save = nil;
+ done = down = 0;
+
+ p = stringsize(font, " ");
+ h = p.y;
+ w = p.x;
+
+ o = m->xy;
+ while(!done){+ p = stringsize(font, buf ? buf : "");
+ if(ask && ask[0]){+ if(buf) p.x += w;
+ p.x += stringwidth(font, ask);
+ }
+ r = rectaddpt(insetrect(Rpt(ZP, p), -4), o);
+ p.x = 0;
+ r = rectsubpt(r, p);
+
+ p = ZP;
+ if(r.min.x < screen->r.min.x)
+ p.x = screen->r.min.x - r.min.x;
+ if(r.min.y < screen->r.min.y)
+ p.y = screen->r.min.y - r.min.y;
+ r = rectaddpt(r, p);
+ p = ZP;
+ if(r.max.x > screen->r.max.x)
+ p.x = r.max.x - screen->r.max.x;
+ if(r.max.y > screen->r.max.y)
+ p.y = r.max.y - screen->r.max.y;
+ r = rectsubpt(r, p);
+
+ r = insetrect(r, -2);
+ if(scr){+ if(b == nil)
+ b = allocwindow(scr, r, Refbackup, DWhite);
+ if(b == nil)
+ scr = nil;
+ }
+ if(scr == nil && save == nil){+ if(b == nil)
+ b = screen;
+ save = allocimage(display, r, b->chan, 0, DNofill);
+ if(save == nil){+ n = -1;
+ break;
+ }
+ draw(save, r, b, nil, r.min);
+ }
+ draw(b, r, backcol, nil, ZP);
+ border(b, r, 2, bordcol, ZP);
+ p = addpt(r.min, Pt(6, 6));
+ if(ask && ask[0]){+ p = string(b, p, bordcol, ZP, font, ask);
+ if(buf) p.x += w;
+ }
+ if(buf){+ t = p;
+ p = stringn(b, p, txtcol, ZP, font, buf, utfnlen(buf, tick));
+ draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), txtcol, nil, ZP);
+ draw(b, Rect(p.x, p.y, p.x+1, p.y+h), txtcol, nil, ZP);
+ draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), txtcol, nil, ZP);
+ p = string(b, p, txtcol, ZP, font, buf+tick);
+ }
+ flushimage(display, 1);
+
+nodraw:
+ switch((*_input)(m, c, &k)){+ case -1:
+ done = 1;
+ n = -1;
+ break;
+ case 1:
+ if(buf == nil || k == Keof || k == '\n'){+ done = 1;
+ break;
+ }
+ if(k == Knack || k == Kesc){+ done = !n;
+ buf[n = tick = 0] = 0;
+ break;
+ }
+ if(k == Ksoh || k == Khome){+ tick = 0;
+ continue;
+ }
+ if(k == Kenq || k == Kend){+ tick = n;
+ continue;
+ }
+ if(k == Kright){+ if(tick < n)
+ tick += chartorune(&k, buf+tick);
+ continue;
+ }
+ if(k == Kleft){+ for(i = 0; i < n; i += l){+ l = chartorune(&k, buf+i);
+ if(i+l >= tick){+ tick = i;
+ break;
+ }
+ }
+ continue;
+ }
+ if(k == Ketb){+ l = tick;
+ while(tick > 0){+ tick--;
+ if(tick == 0 ||
+ strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1]))+ break;
+ }
+ memmove(buf+tick, buf+l, n-l);
+ buf[n -= l-tick] = 0;
+ break;
+ }
+ if(k == Kbs){+ if(tick <= 0)
+ continue;
+ for(i = 0; i < n; i += l){+ l = chartorune(&k, buf+i);
+ if(i+l >= tick){+ memmove(buf+i, buf+i+l, n - (i+l));
+ buf[n -= l] = 0;
+ tick -= l;
+ break;
+ }
+ }
+ break;
+ }
+ if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec)
+ continue;
+ if((len-n) <= (l = runelen(k)))
+ continue;
+ memmove(buf+tick+l, buf+tick, n - tick);
+ runetochar(buf+tick, &k);
+ buf[n += l] = 0;
+ tick += l;
+ break;
+ case 0:
+ if(!ptinrect(m->xy, r)){+ down = 0;
+ goto nodraw;
+ }
+ if(m->buttons & 7){+ down = 1;
+ if(buf && m->xy.x >= (t.x - w)){+ down = 0;
+ for(i = 0; i < n; i += l){+ l = chartorune(&k, buf+i);
+ t.x += stringnwidth(font, buf+i, 1);
+ if(t.x > m->xy.x)
+ break;
+ }
+ tick = i;
+ }
+ continue;
+ }
+ done = down;
+ break;
+ }
+
+ if(b != screen) {+ freeimage(b);
+ b = nil;
+ } else {+ draw(b, save->r, save, nil, save->r.min);
+ freeimage(save);
+ save = nil;
+ }
+ }
+
+ replclipr(screen, 0, sc);
+
+ freeimage(backcol);
+ freeimage(bordcol);
+ flushimage(display, 1);
+
+ return n;
+}
--- /dev/null
+++ b/sys/src/libdraw/genmenuhit.c
@@ -1,0 +1,297 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+
+enum
+{+ Margin = 4, /* outside to text */
+ Border = 2, /* outside to selection boxes */
+ Blackborder = 2, /* width of outlining border */
+ Vspacing = 2, /* extra spacing between lines of text */
+ Maxunscroll = 25, /* maximum #entries before scrolling turns on */
+ Nscroll = 20, /* number entries in scrolling part */
+ Scrollwid = 14, /* width of scroll bar */
+ Gap = 4, /* between text and scroll bar */
+};
+
+static Image *menutxt;
+static Image *back;
+static Image *high;
+static Image *bord;
+static Image *text;
+static Image *htext;
+
+static void
+menucolors(void)
+{+ enum{+ Cback,
+ Chigh,
+ Cbord,
+ Ctext,
+ Chtext,
+ Cmtext,
+ Ncols,
+ };
+ Theme th[Ncols] = {+ [Cback] { "menuback", 0xEAFFEAFF },+ [Chigh] { "menuhigh", DDarkgreen },+ [Cbord] { "menubord", DMedgreen },+ [Ctext] { "menutext", DBlack },+ [Chtext]{ "menuhtext", 0xEAFFEAFF },+ [Cmtext]{ "menubar", DDarkgreen },+ };
+
+ readtheme(th, nelem(th), nil);
+ back = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
+ high = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chigh].c);
+ bord = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
+ text = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
+ htext = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chtext].c);
+ menutxt = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cmtext].c);
+ if(back == nil || high == nil || bord == nil
+ || text == nil || htext == nil || menutxt == nil)
+ goto Error;
+ return;
+
+ Error:
+ freeimage(menutxt);
+ freeimage(back);
+ freeimage(high);
+ freeimage(bord);
+ freeimage(menutxt);
+ freeimage(htext);
+ freeimage(text);
+ menutxt = display->black;
+ back = display->white;
+ high = display->black;
+ bord = display->black;
+ text = display->black;
+ htext = display->white;
+ menutxt = display->black;
+}
+
+/*
+ * r is a rectangle holding the text elements.
+ * return the rectangle, including its black edge, holding element i.
+ */
+static Rectangle
+menurect(Rectangle r, int i)
+{+ if(i < 0)
+ return Rect(0, 0, 0, 0);
+ r.min.y += (font->height+Vspacing)*i;
+ r.max.y = r.min.y+font->height+Vspacing;
+ return insetrect(r, Border-Margin);
+}
+
+/*
+ * r is a rectangle holding the text elements.
+ * return the element number containing p.
+ */
+static int
+menusel(Rectangle r, Point p)
+{+ if(!ptinrect(p, r))
+ return -1;
+ return (p.y-r.min.y)/(font->height+Vspacing);
+}
+
+static void
+paintitem(Image *m, Menu *menu, Rectangle textr, int off, int i, int highlight, Image *save, Image *restore)
+{+ char *item;
+ Rectangle r;
+ Point pt;
+
+ if(i < 0)
+ return;
+ r = menurect(textr, i);
+ if(restore){+ draw(m, r, restore, nil, restore->r.min);
+ return;
+ }
+ if(save)
+ draw(save, save->r, m, nil, r.min);
+ item = menu->item? menu->item[i+off] : (*menu->gen)(i+off);
+ pt.x = (textr.min.x+textr.max.x-stringwidth(font, item))/2;
+ pt.y = textr.min.y+i*(font->height+Vspacing);
+ draw(m, r, highlight? high : back, nil, pt);
+ string(m, pt, highlight? htext : text, pt, font, item);
+}
+
+/*
+ * menur is a rectangle holding all the highlightable text elements.
+ * track mouse while inside the box, return what's selected when button
+ * is raised, -1 as soon as it leaves box.
+ * invariant: nothing is highlighted on entry or exit.
+ */
+static int
+menuscan(Image *b, Menu *menu, int but, Mouse *m, void (*_readmouse)(Mouse*), Rectangle textr, int off, int lasti, Image *save)
+{+ int i;
+
+ paintitem(b, menu, textr, off, lasti, 1, save, nil);
+ for((*_readmouse)(m); m->buttons & (1<<(but-1)); (*_readmouse)(m)){+ i = menusel(textr, m->xy);
+ if(i != -1 && i == lasti)
+ continue;
+ paintitem(b, menu, textr, off, lasti, 0, nil, save);
+ if(i == -1)
+ return i;
+ lasti = i;
+ paintitem(b, menu, textr, off, lasti, 1, save, nil);
+ }
+ return lasti;
+}
+
+static void
+menupaint(Image *b, Menu *menu, Rectangle textr, int off, int nitemdrawn)
+{+ int i;
+
+ draw(b, insetrect(textr, Border-Margin), back, nil, ZP);
+ for(i = 0; i<nitemdrawn; i++)
+ paintitem(b, menu, textr, off, i, 0, nil, nil);
+}
+
+static void
+menuscrollpaint(Image *b, Rectangle scrollr, int off, int nitem, int nitemdrawn)
+{+ Rectangle r;
+
+ draw(b, scrollr, back, nil, ZP);
+ r.min.x = scrollr.min.x;
+ r.max.x = scrollr.max.x;
+ r.min.y = scrollr.min.y + (Dy(scrollr)*off)/nitem;
+ r.max.y = scrollr.min.y + (Dy(scrollr)*(off+nitemdrawn))/nitem;
+ if(r.max.y < r.min.y+2)
+ r.max.y = r.min.y+2;
+ border(b, r, 1, bord, ZP);
+ draw(b, insetrect(r, 1), menutxt, nil, ZP);
+}
+
+int
+genmenuhit(int but, Mouse *m, void (*_readmouse)(Mouse*), void (*_moveto)(Mouse*, Point), Menu *menu, Screen *scr)
+{+ int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem;
+ int scrolling;
+ Rectangle r, menur, sc, textr, scrollr;
+ Image *b, *save, *backup;
+ Point pt;
+ char *item;
+
+ if(back == nil)
+ menucolors();
+ sc = screen->clipr;
+ replclipr(screen, 0, screen->r);
+ maxwid = 0;
+ for(nitem = 0;
+ item = menu->item? menu->item[nitem] : (*menu->gen)(nitem);
+ nitem++){+ i = stringwidth(font, item);
+ if(i > maxwid)
+ maxwid = i;
+ }
+ if(menu->lasthit<0 || menu->lasthit>=nitem)
+ menu->lasthit = 0;
+ screenitem = (Dy(screen->r)-10)/(font->height+Vspacing);
+ if(nitem>Maxunscroll || nitem>screenitem){+ scrolling = 1;
+ nitemdrawn = Nscroll;
+ if(nitemdrawn > screenitem)
+ nitemdrawn = screenitem;
+ wid = maxwid + Gap + Scrollwid;
+ off = menu->lasthit - nitemdrawn/2;
+ if(off < 0)
+ off = 0;
+ if(off > nitem-nitemdrawn)
+ off = nitem-nitemdrawn;
+ lasti = menu->lasthit-off;
+ }else{+ scrolling = 0;
+ nitemdrawn = nitem;
+ wid = maxwid;
+ off = 0;
+ lasti = menu->lasthit;
+ }
+ r = insetrect(Rect(0, 0, wid, nitemdrawn*(font->height+Vspacing)), -Margin);
+ r = rectsubpt(r, Pt(wid/2, lasti*(font->height+Vspacing)+font->height/2));
+ r = rectaddpt(r, m->xy);
+ pt = ZP;
+ if(r.max.x>screen->r.max.x)
+ pt.x = screen->r.max.x-r.max.x;
+ if(r.max.y>screen->r.max.y)
+ pt.y = screen->r.max.y-r.max.y;
+ if(r.min.x<screen->r.min.x)
+ pt.x = screen->r.min.x-r.min.x;
+ if(r.min.y<screen->r.min.y)
+ pt.y = screen->r.min.y-r.min.y;
+ menur = rectaddpt(r, pt);
+ textr.max.x = menur.max.x-Margin;
+ textr.min.x = textr.max.x-maxwid;
+ textr.min.y = menur.min.y+Margin;
+ textr.max.y = textr.min.y + nitemdrawn*(font->height+Vspacing);
+ if(scrolling){+ scrollr = insetrect(menur, Border);
+ scrollr.max.x = scrollr.min.x+Scrollwid;
+ }else
+ scrollr = Rect(0, 0, 0, 0);
+
+ if(scr){+ b = allocwindow(scr, menur, Refbackup, DWhite);
+ if(b == nil)
+ b = screen;
+ backup = nil;
+ }else{+ b = screen;
+ backup = allocimage(display, menur, screen->chan, 0, -1);
+ if(backup)
+ draw(backup, menur, screen, nil, menur.min);
+ }
+ draw(b, menur, back, nil, ZP);
+ border(b, menur, Blackborder, bord, ZP);
+ save = allocimage(display, menurect(textr, 0), screen->chan, 0, -1);
+ r = menurect(textr, lasti);
+ if(pt.x || pt.y)
+ (*_moveto)(m, divpt(addpt(r.min, r.max), 2));
+ menupaint(b, menu, textr, off, nitemdrawn);
+ if(scrolling)
+ menuscrollpaint(b, scrollr, off, nitem, nitemdrawn);
+ while(m->buttons & (1<<(but-1))){+ lasti = menuscan(b, menu, but, m, _readmouse, textr, off, lasti, save);
+ if(lasti >= 0)
+ break;
+ while(!ptinrect(m->xy, textr) && (m->buttons & (1<<(but-1)))){+ if(scrolling && ptinrect(m->xy, scrollr)){+ noff = ((m->xy.y-scrollr.min.y)*nitem)/Dy(scrollr);
+ noff -= nitemdrawn/2;
+ if(noff < 0)
+ noff = 0;
+ if(noff > nitem-nitemdrawn)
+ noff = nitem-nitemdrawn;
+ if(noff != off){+ off = noff;
+ menupaint(b, menu, textr, off, nitemdrawn);
+ menuscrollpaint(b, scrollr, off, nitem, nitemdrawn);
+ }
+ }
+ (*_readmouse)(m);
+ }
+ }
+ if(b != screen)
+ freeimage(b);
+ if(backup){+ draw(screen, menur, backup, nil, menur.min);
+ freeimage(backup);
+ }
+ freeimage(save);
+ replclipr(screen, 0, sc);
+ flushimage(display, 1);
+ if(lasti >= 0){+ menu->lasthit = lasti+off;
+ return menu->lasthit;
+ }
+ return -1;
+}
--- a/sys/src/libdraw/menuhit.c
+++ /dev/null
@@ -1,298 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <draw.h>
-#include <thread.h>
-#include <mouse.h>
-
-enum
-{- Margin = 4, /* outside to text */
- Border = 2, /* outside to selection boxes */
- Blackborder = 2, /* width of outlining border */
- Vspacing = 2, /* extra spacing between lines of text */
- Maxunscroll = 25, /* maximum #entries before scrolling turns on */
- Nscroll = 20, /* number entries in scrolling part */
- Scrollwid = 14, /* width of scroll bar */
- Gap = 4, /* between text and scroll bar */
-};
-
-static Image *menutxt;
-static Image *back;
-static Image *high;
-static Image *bord;
-static Image *text;
-static Image *htext;
-
-static
-void
-menucolors(void)
-{- enum{- Cback,
- Chigh,
- Cbord,
- Ctext,
- Chtext,
- Cmtext,
- Ncols,
- };
- Theme th[Ncols] = {- [Cback] { "menuback", 0xEAFFEAFF },- [Chigh] { "menuhigh", DDarkgreen },- [Cbord] { "menubord", DMedgreen },- [Ctext] { "menutext", DBlack },- [Chtext]{ "menuhtext", 0xEAFFEAFF },- [Cmtext]{ "menubar", DDarkgreen },- };
-
- readtheme(th, nelem(th), nil);
- back = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cback].c);
- high = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chigh].c);
- bord = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cbord].c);
- text = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Ctext].c);
- htext = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Chtext].c);
- menutxt = allocimage(display, Rect(0,0,1,1), screen->chan, 1, th[Cmtext].c);
- if(back == nil || high == nil || bord == nil
- || text == nil || htext == nil || menutxt == nil)
- goto Error;
- return;
-
- Error:
- freeimage(back);
- freeimage(high);
- freeimage(bord);
- freeimage(menutxt);
- freeimage(text);
- freeimage(htext);
- back = display->white;
- high = display->black;
- bord = display->black;
- text = display->black;
- htext = display->white;
- menutxt = display->black;
-}
-
-/*
- * r is a rectangle holding the text elements.
- * return the rectangle, including its black edge, holding element i.
- */
-static Rectangle
-menurect(Rectangle r, int i)
-{- if(i < 0)
- return Rect(0, 0, 0, 0);
- r.min.y += (font->height+Vspacing)*i;
- r.max.y = r.min.y+font->height+Vspacing;
- return insetrect(r, Border-Margin);
-}
-
-/*
- * r is a rectangle holding the text elements.
- * return the element number containing p.
- */
-static int
-menusel(Rectangle r, Point p)
-{- if(!ptinrect(p, r))
- return -1;
- return (p.y-r.min.y)/(font->height+Vspacing);
-}
-
-static
-void
-paintitem(Image *m, Menu *menu, Rectangle textr, int off, int i, int highlight, Image *save, Image *restore)
-{- char *item;
- Rectangle r;
- Point pt;
-
- if(i < 0)
- return;
- r = menurect(textr, i);
- if(restore){- draw(m, r, restore, nil, restore->r.min);
- return;
- }
- if(save)
- draw(save, save->r, m, nil, r.min);
- item = menu->item? menu->item[i+off] : (*menu->gen)(i+off);
- pt.x = (textr.min.x+textr.max.x-stringwidth(font, item))/2;
- pt.y = textr.min.y+i*(font->height+Vspacing);
- draw(m, r, highlight? high : back, nil, pt);
- string(m, pt, highlight? htext : text, pt, font, item);
-}
-
-/*
- * menur is a rectangle holding all the highlightable text elements.
- * track mouse while inside the box, return what's selected when button
- * is raised, -1 as soon as it leaves box.
- * invariant: nothing is highlighted on entry or exit.
- */
-static int
-menuscan(Image *m, Menu *menu, int but, Mousectl *mc, Rectangle textr, int off, int lasti, Image *save)
-{- int i;
-
- paintitem(m, menu, textr, off, lasti, 1, save, nil);
- for(readmouse(mc); mc->buttons & (1<<(but-1)); readmouse(mc)){- i = menusel(textr, mc->xy);
- if(i != -1 && i == lasti)
- continue;
- paintitem(m, menu, textr, off, lasti, 0, nil, save);
- if(i == -1)
- return i;
- lasti = i;
- paintitem(m, menu, textr, off, lasti, 1, save, nil);
- }
- return lasti;
-}
-
-static void
-menupaint(Image *m, Menu *menu, Rectangle textr, int off, int nitemdrawn)
-{- int i;
-
- draw(m, insetrect(textr, Border-Margin), back, nil, ZP);
- for(i = 0; i<nitemdrawn; i++)
- paintitem(m, menu, textr, off, i, 0, nil, nil);
-}
-
-static void
-menuscrollpaint(Image *m, Rectangle scrollr, int off, int nitem, int nitemdrawn)
-{- Rectangle r;
-
- draw(m, scrollr, back, nil, ZP);
- r.min.x = scrollr.min.x;
- r.max.x = scrollr.max.x;
- r.min.y = scrollr.min.y + (Dy(scrollr)*off)/nitem;
- r.max.y = scrollr.min.y + (Dy(scrollr)*(off+nitemdrawn))/nitem;
- if(r.max.y < r.min.y+2)
- r.max.y = r.min.y+2;
- border(m, r, 1, bord, ZP);
- draw(m, insetrect(r, 1), menutxt, nil, ZP);
-}
-
-int
-menuhit(int but, Mousectl *mc, Menu *menu, Screen *scr)
-{- int i, nitem, nitemdrawn, maxwid, lasti, off, noff, wid, screenitem;
- int scrolling;
- Rectangle r, menur, sc, textr, scrollr;
- Image *b, *save, *backup;
- Point pt;
- char *item;
-
- if(back == nil)
- menucolors();
- sc = screen->clipr;
- replclipr(screen, 0, screen->r);
- maxwid = 0;
- for(nitem = 0;
- item = menu->item? menu->item[nitem] : (*menu->gen)(nitem);
- nitem++){- i = stringwidth(font, item);
- if(i > maxwid)
- maxwid = i;
- }
- if(menu->lasthit<0 || menu->lasthit>=nitem)
- menu->lasthit = 0;
- screenitem = (Dy(screen->r)-10)/(font->height+Vspacing);
- if(nitem>Maxunscroll || nitem>screenitem){- scrolling = 1;
- nitemdrawn = Nscroll;
- if(nitemdrawn > screenitem)
- nitemdrawn = screenitem;
- wid = maxwid + Gap + Scrollwid;
- off = menu->lasthit - nitemdrawn/2;
- if(off < 0)
- off = 0;
- if(off > nitem-nitemdrawn)
- off = nitem-nitemdrawn;
- lasti = menu->lasthit-off;
- }else{- scrolling = 0;
- nitemdrawn = nitem;
- wid = maxwid;
- off = 0;
- lasti = menu->lasthit;
- }
- r = insetrect(Rect(0, 0, wid, nitemdrawn*(font->height+Vspacing)), -Margin);
- r = rectsubpt(r, Pt(wid/2, lasti*(font->height+Vspacing)+font->height/2));
- r = rectaddpt(r, mc->xy);
- pt = ZP;
- if(r.max.x>screen->r.max.x)
- pt.x = screen->r.max.x-r.max.x;
- if(r.max.y>screen->r.max.y)
- pt.y = screen->r.max.y-r.max.y;
- if(r.min.x<screen->r.min.x)
- pt.x = screen->r.min.x-r.min.x;
- if(r.min.y<screen->r.min.y)
- pt.y = screen->r.min.y-r.min.y;
- menur = rectaddpt(r, pt);
- textr.max.x = menur.max.x-Margin;
- textr.min.x = textr.max.x-maxwid;
- textr.min.y = menur.min.y+Margin;
- textr.max.y = textr.min.y + nitemdrawn*(font->height+Vspacing);
- if(scrolling){- scrollr = insetrect(menur, Border);
- scrollr.max.x = scrollr.min.x+Scrollwid;
- }else
- scrollr = Rect(0, 0, 0, 0);
-
- if(scr){- b = allocwindow(scr, menur, Refbackup, DWhite);
- if(b == nil)
- b = screen;
- backup = nil;
- }else{- b = screen;
- backup = allocimage(display, menur, screen->chan, 0, -1);
- if(backup)
- draw(backup, menur, screen, nil, menur.min);
- }
- draw(b, menur, back, nil, ZP);
- border(b, menur, Blackborder, bord, ZP);
- save = allocimage(display, menurect(textr, 0), screen->chan, 0, -1);
- r = menurect(textr, lasti);
- if(pt.x || pt.y)
- moveto(mc, divpt(addpt(r.min, r.max), 2));
- menupaint(b, menu, textr, off, nitemdrawn);
- if(scrolling)
- menuscrollpaint(b, scrollr, off, nitem, nitemdrawn);
- while(mc->buttons & (1<<(but-1))){- lasti = menuscan(b, menu, but, mc, textr, off, lasti, save);
- if(lasti >= 0)
- break;
- while(!ptinrect(mc->xy, textr) && (mc->buttons & (1<<(but-1)))){- if(scrolling && ptinrect(mc->xy, scrollr)){- noff = ((mc->xy.y-scrollr.min.y)*nitem)/Dy(scrollr);
- noff -= nitemdrawn/2;
- if(noff < 0)
- noff = 0;
- if(noff > nitem-nitemdrawn)
- noff = nitem-nitemdrawn;
- if(noff != off){- off = noff;
- menupaint(b, menu, textr, off, nitemdrawn);
- menuscrollpaint(b, scrollr, off, nitem, nitemdrawn);
- }
- }
- readmouse(mc);
- }
- }
- if(b != screen)
- freeimage(b);
- if(backup){- draw(screen, menur, backup, nil, menur.min);
- freeimage(backup);
- }
- freeimage(save);
- replclipr(screen, 0, sc);
- flushimage(display, 1);
- if(lasti >= 0){- menu->lasthit = lasti+off;
- return menu->lasthit;
- }
- return -1;
-}
--- a/sys/src/libdraw/mkfile
+++ b/sys/src/libdraw/mkfile
@@ -28,6 +28,8 @@
fmt.$O\
font.$O\
freesubfont.$O\
+ genenter.$O\
+ genmenuhit.$O\
getdefont.$O\
getrect.$O\
getsubfont.$O\
--
⑨