ref: 7d29d072f84e97ed311932b3a3cfdbeca317f4f9
parent: bc69d3c62762f155e54e487f2145cd7fe3224ce7
author: glenda <glenda@9front.local>
date: Sun Sep 5 19:41:28 EDT 2021
renamed from sel/line to just dmenu
--- /dev/null
+++ b/dmenu.c
@@ -1,0 +1,367 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <draw.h>
+#include <event.h>
+#include <keyboard.h>
+
+#define Ctl(c) ((c) - 64)
+#define PROMPT " > "
+
+enum
+{+ BACK,
+ HBACK,
+ TEXT,
+ HTEXT,
+ NCOLORS
+};
+
+Image *color[NCOLORS];
+char **lines, **matches, *buffer;
+usize nlines, nmatches, scroll;
+Rune kbinput[512];
+int selected;
+
+static void
+readbuffer(void)
+{+ Biobuf *bp;
+ char *line, *s;
+
+ if((bp = Bfdopen(0, OREAD)) == nil)
+ sysfatal("setting buffering on fd0: %r");+ if((buffer = Brdstr(bp, '\0', 1)) == nil)
+ sysfatal("reading input lines: %r");+
+ for(line = s = buffer; s = strchr(s, '\n'); line = ++s){+ *s = '\0';
+ if((lines = realloc(lines, ++nlines * sizeof *lines)) == nil)
+ sysfatal("malloc: %r");+ lines[nlines-1] = line;
+ }
+
+ if((matches = malloc(nlines * sizeof *lines)) == nil)
+ sysfatal("malloc: %r");+ memmove(matches, lines, nlines * sizeof *lines);
+ nmatches = nlines;
+}
+
+static Point
+linetopoint(int ln)
+{+ ln -= scroll;
+ return Pt(screen->r.min.x, screen->r.min.y + (ln + 2) * font->height);
+}
+
+static int
+pointtoline(Point pt)
+{+ return (pt.y - screen->r.min.y) / font->height - 2 + scroll;
+}
+
+static void
+drawbackground(Point pt, Image *color)
+{+ draw(screen,
+ Rect(screen->r.min.x, pt.y, screen->r.max.x, pt.y + font->height),
+ color, nil, ZP);
+}
+
+static Point
+tabstring(Image *dst, Point dp, Image *src, Point sp, Font *f, char *s)
+{+ Rune r[2] = {L'0', L'\0'};+ int n, w0, x;
+ Point op;
+
+ op = dp;
+ w0 = stringwidth(f, "0");
+ for(; *s && (n = chartorune(r, s)) > 0; s += n){+ if(r[0] == '\t'){+ x = 8 * w0 - (dp.x - op.x) % (8 * w0);
+ sp.x += x;
+ dp.x += x;
+ }else{+ dp = runestring(dst, dp, src, sp, f, r);
+ }
+ }
+ return dp;
+}
+
+static void
+drawprompt(void)
+{+ Point pt;
+ char buf[512];
+
+ snprint(buf, sizeof buf, PROMPT"%S▏", kbinput);
+ pt = Pt(screen->r.max.x, screen->r.min.y + font->height * 2);
+ draw(screen, Rpt(screen->r.min, pt), color[BACK], nil, ZP);
+ pt = Pt(screen->r.min.x, screen->r.min.y + font->height);
+ tabstring(screen, pt, color[TEXT], ZP, font, buf);
+}
+
+static int
+drawline(int ln)
+{+ Point pt = linetopoint(ln);
+ Image *bgcolor, *txcolor;
+
+ if(ln < scroll)
+ return 1;
+ if(ln == selected){+ bgcolor = color[HBACK];
+ txcolor = color[HTEXT];
+ }else{+ bgcolor = color[BACK];
+ txcolor = color[TEXT];
+ }
+ pt.x += stringwidth(font, PROMPT);
+ drawbackground(pt, bgcolor);
+ if(ln < nmatches)
+ tabstring(screen, pt, txcolor, ZP, font, matches[ln]);
+ return pt.y < screen->r.max.y;
+}
+
+void
+eresized(int new)
+{+ int i;
+
+ if(new && getwindow(display, Refnone) < 0)
+ sysfatal("resize failed: %r");+
+ drawprompt();
+ for(i = scroll; drawline(i); i++);
+}
+
+int
+match(char *s, char **words, int nwords)
+{+ char **w;
+
+ if(nwords == 0)
+ return 1;
+ for(w = words; w < words + nwords; w++)
+ if(cistrstr(s, *w) == nil)
+ return 0;
+ return 1;
+}
+
+void
+filter(char **lines, int nlines)
+{+ char *buf, *words[64], **l, **m;
+ int nwords;
+
+ if((buf = smprint("%S", kbinput)) == nil)+ sysfatal("malloc");+ nwords = tokenize(buf, words, sizeof words / sizeof *words);
+
+ nmatches = 0;
+ m = matches;
+ for(l = lines; l < lines + nlines; l++)
+ if(match(*l, words, nwords)){+ *m++ = *l;
+ nmatches++;
+ }
+
+ selected = 0;
+ scroll = 0;
+ free(buf);
+ eresized(0); /* possibly different lines: redraw everything */
+}
+
+static void
+kbadd(Rune r)
+{+ int len = runestrlen(kbinput);
+
+ if(len == sizeof kbinput / sizeof *kbinput)
+ return;
+ kbinput[len++] = r;
+ kbinput[len] = L'\0';
+
+ filter(matches, nmatches);
+}
+
+static void
+kbbackspace(void)
+{+ usize len = runestrlen(kbinput);
+
+ if(len == 0)
+ return;
+ kbinput[len - 1] = L'\0';
+
+ filter(lines, nlines);
+}
+
+static void
+kbdelword(void)
+{+ usize len = runestrlen(kbinput);
+
+ if(len == 0)
+ return;
+ while(len > 0 && isspacerune(kbinput[len-1]))
+ len--;
+ while(len > 0 && !isspacerune(kbinput[len-1]))
+ len--;
+ kbinput[len] = L'\0';
+
+ filter(lines, nlines);
+}
+
+static void
+kbclear(void)
+{+ kbinput[0] = L'\0';
+
+ filter(lines, nlines);
+}
+
+static void
+kbmove(int n)
+{+ int old = selected;
+
+ if(selected + n < 0)
+ selected = 0;
+ else if(selected + n >= nmatches)
+ selected = nmatches - 1;
+ else
+ selected += n;
+
+ drawline(old);
+ drawline(selected);
+}
+
+static void
+kbscroll(int percent)
+{+ int ln = Dy(screen->r) / font->height * percent / 100;
+
+ if(ln < 0 && abs(ln) > scroll)
+ scroll = 0;
+ else if(ln > 0 && scroll + ln >= nmatches)
+ scroll = nmatches - 1 + (nmatches > 0);
+ else
+ scroll += ln;
+
+ eresized(0);
+}
+
+static void
+mselect(Point pt)
+{+ int old, sel = pointtoline(pt);
+
+ if(sel < 0)
+ sel = 0;
+ if(nmatches > 0 && sel >= nmatches)
+ sel = nmatches - 1;
+ if(sel != selected){+ old = selected;
+ selected = sel;
+ drawline(old);
+ drawline(sel);
+ }
+}
+
+static void
+usage(void)
+{+ print("usage: %s [-b] <choices\n", argv0);+ exits("usage");+}
+
+void
+main(int argc, char **argv)
+{+ Event e;
+ int bflag = 0;
+
+ ARGBEGIN{+ case 'b':
+ bflag = 1;
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ readbuffer();
+
+ if(initdraw(nil, nil, "linesel") < 0)
+ sysfatal("initdraw: %r");+
+ if(bflag){+ color[TEXT] = display->white;
+ color[BACK] = display->black;
+ }else{+ color[TEXT] = display->black;
+ color[BACK] = display->white;
+ }
+ color[HTEXT] = display->black;
+ color[HBACK] = allocimage(display,
+ Rect(0,0,1,1), screen->chan, 1, DPaleyellow);
+
+ eresized(0);
+
+ einit(Emouse|Ekeyboard);
+ for(;;){+ switch(event(&e)){+ case -1:
+ sysfatal("watching events: %r");+
+ case Ekeyboard:
+ switch(e.kbdc){+ case Kdel:
+ exits("interrupted with Del");+ case '\n':
+ goto End;
+ case Kbs:
+ kbbackspace();
+ break;
+ case Ctl('W'):+ kbdelword();
+ break;
+ case Ctl('U'):+ kbclear();
+ break;
+ case Kup:
+ kbmove(-1);
+ break;
+ case Kdown:
+ kbmove(+1);
+ break;
+ case Kpgdown:
+ kbscroll(+40);
+ break;
+ case Kpgup:
+ kbscroll(-40);
+ break;
+ default:
+ kbadd(e.kbdc);
+ break;
+ }
+ break;
+
+ case Emouse:
+ if(e.mouse.buttons&1)
+ mselect(e.mouse.xy);
+ if(e.mouse.buttons&4)
+ goto End;
+ if(e.mouse.buttons&8)
+ kbscroll(-40);
+ if(e.mouse.buttons&16)
+ kbscroll(+40);
+ break;
+ }
+ }
+End:
+ if(nmatches > 0)
+ print("%s\n", matches[selected]);+ exits(nil);
+}
--- a/line.c
+++ /dev/null
@@ -1,365 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <bio.h>
-#include <draw.h>
-#include <event.h>
-#include <keyboard.h>
-
-#define Ctl(c) ((c) - 64)
-#define PROMPT " > "
-
-enum
-{- BACK,
- HBACK,
- TEXT,
- HTEXT,
- NCOLORS
-};
-
-Image *color[NCOLORS];
-char **lines, **matches, *buffer;
-usize nlines, nmatches, scroll;
-Rune kbinput[512];
-int selected;
-
-static void
-readbuffer(void)
-{- Biobuf *bp;
- char *line, *s;
-
- if((bp = Bfdopen(0, OREAD)) == nil)
- sysfatal("setting buffering on fd0: %r");- if((buffer = Brdstr(bp, '\0', 1)) == nil)
- sysfatal("reading input lines: %r");-
- for(line = s = buffer; s = strchr(s, '\n'); line = ++s){- *s = '\0';
- if((lines = realloc(lines, ++nlines * sizeof *lines)) == nil)
- sysfatal("malloc: %r");- lines[nlines-1] = line;
- }
-
- if((matches = malloc(nlines * sizeof *lines)) == nil)
- sysfatal("malloc: %r");- memmove(matches, lines, nlines * sizeof *lines);
- nmatches = nlines;
-}
-
-static Point
-linetopoint(int ln)
-{- ln -= scroll;
- return Pt(screen->r.min.x, screen->r.min.y + (ln + 2) * font->height);
-}
-
-static int
-pointtoline(Point pt)
-{- return (pt.y - screen->r.min.y) / font->height - 2 + scroll;
-}
-
-static void
-drawbackground(Point pt, Image *color)
-{- draw(screen,
- Rect(screen->r.min.x, pt.y, screen->r.max.x, pt.y + font->height),
- color, nil, ZP);
-}
-
-static Point
-tabstring(Image *dst, Point dp, Image *src, Point sp, Font *f, char *s)
-{- Rune r[2] = {L'0', L'\0'};- int n, w0, x;
- Point op;
-
- op = dp;
- w0 = stringwidth(f, "0");
- for(; *s && (n = chartorune(r, s)) > 0; s += n){- if(r[0] == '\t'){- x = 8 * w0 - (dp.x - op.x) % (8 * w0);
- sp.x += x;
- dp.x += x;
- }else{- dp = runestring(dst, dp, src, sp, f, r);
- }
- }
- return dp;
-}
-
-static void
-drawprompt(void)
-{- Point pt;
- char buf[512];
-
- snprint(buf, sizeof buf, PROMPT"%S▏", kbinput);
- pt = Pt(screen->r.max.x, screen->r.min.y + font->height * 2);
- draw(screen, Rpt(screen->r.min, pt), color[BACK], nil, ZP);
- pt = Pt(screen->r.min.x, screen->r.min.y + font->height);
- tabstring(screen, pt, color[TEXT], ZP, font, buf);
-}
-
-static int
-drawline(int ln)
-{- Point pt = linetopoint(ln);
- Image *bgcolor, *txcolor;
-
- if(ln < scroll)
- return 1;
- if(ln == selected){- bgcolor = color[HBACK];
- txcolor = color[HTEXT];
- }else{- bgcolor = color[BACK];
- txcolor = color[TEXT];
- }
- pt.x += stringwidth(font, PROMPT);
- drawbackground(pt, bgcolor);
- if(ln < nmatches)
- tabstring(screen, pt, txcolor, ZP, font, matches[ln]);
- return pt.y < screen->r.max.y;
-}
-
-void
-eresized(int new)
-{- int i;
-
- if(new && getwindow(display, Refnone) < 0)
- sysfatal("resize failed: %r");-
- drawprompt();
- for(i = scroll; drawline(i); i++);
-}
-
-int
-match(char *s, char **words, int nwords)
-{- char **w;
-
- if(nwords == 0)
- return 1;
- for(w = words; w < words + nwords; w++)
- if(cistrstr(s, *w) == nil)
- return 0;
- return 1;
-}
-
-void
-filter(char **lines, int nlines)
-{- char *buf, *words[64], **l, **m;
- int nwords;
-
- if((buf = smprint("%S", kbinput)) == nil)- sysfatal("malloc");- nwords = tokenize(buf, words, sizeof words / sizeof *words);
-
- nmatches = 0;
- m = matches;
- for(l = lines; l < lines + nlines; l++)
- if(match(*l, words, nwords)){- *m++ = *l;
- nmatches++;
- }
-
- selected = 0;
- scroll = 0;
- free(buf);
- eresized(0); /* possibly different lines: redraw everything */
-}
-
-static void
-kbadd(Rune r)
-{- int len = runestrlen(kbinput);
-
- if(len == sizeof kbinput / sizeof *kbinput)
- return;
- kbinput[len++] = r;
- kbinput[len] = L'\0';
-
- filter(matches, nmatches);
-}
-
-static void
-kbbackspace(void)
-{- usize len = runestrlen(kbinput);
-
- if(len == 0)
- return;
- kbinput[len - 1] = L'\0';
-
- filter(lines, nlines);
-}
-
-static void
-kbdelword(void)
-{- usize len = runestrlen(kbinput);
-
- if(len == 0)
- return;
- while(len > 0 && isspacerune(kbinput[len-1]))
- len--;
- while(len > 0 && !isspacerune(kbinput[len-1]))
- len--;
- kbinput[len] = L'\0';
-
- filter(lines, nlines);
-}
-
-static void
-kbclear(void)
-{- kbinput[0] = L'\0';
-
- filter(lines, nlines);
-}
-
-static void
-kbmove(int n)
-{- int old = selected;
-
- if(selected + n < 0)
- selected = 0;
- else if(selected + n >= nmatches)
- selected = nmatches - 1;
- else
- selected += n;
- drawline(old);
- drawline(selected);
-}
-
-static void
-kbscroll(int percent)
-{- int ln = Dy(screen->r) / font->height * percent / 100;
-
- if(ln < 0 && abs(ln) > scroll)
- scroll = 0;
- else if(ln > 0 && scroll + ln >= nmatches)
- scroll = nmatches - 1 + (nmatches > 0);
- else
- scroll += ln;
- eresized(0);
-}
-
-static void
-mselect(Point pt)
-{- int old, sel = pointtoline(pt);
-
- if(sel < 0)
- sel = 0;
- if(nmatches > 0 && sel >= nmatches)
- sel = nmatches - 1;
- if(sel != selected){- old = selected;
- selected = sel;
- drawline(old);
- drawline(sel);
- }
-}
-
-static void
-usage(void)
-{- print("usage: %s [-b] <choices\n", argv0);- exits("usage");-}
-
-void
-main(int argc, char **argv)
-{- Event e;
- int bflag = 0;
-
- ARGBEGIN{- case 'b':
- bflag = 1;
- break;
- default:
- usage();
- }ARGEND;
-
- readbuffer();
-
- if(initdraw(nil, nil, "linesel") < 0)
- sysfatal("initdraw: %r");-
- if(bflag){- color[TEXT] = display->white;
- color[BACK] = display->black;
- }else{- color[TEXT] = display->black;
- color[BACK] = display->white;
- }
- color[HTEXT] = display->black;
- color[HBACK] = allocimage(display,
- Rect(0,0,1,1), screen->chan, 1, DPaleyellow);
-
- eresized(0);
-
- einit(Emouse|Ekeyboard);
- for(;;){- switch(event(&e)){- case -1:
- sysfatal("watching events: %r");-
- case Ekeyboard:
- switch(e.kbdc){- case Kdel:
- exits("interrupted with Del");- case '\n':
- goto End;
- case Kbs:
- kbbackspace();
- break;
- case Ctl('W'):- kbdelword();
- break;
- case Ctl('U'):- kbclear();
- break;
- case Kup:
- kbmove(-1);
- break;
- case Kdown:
- kbmove(+1);
- break;
- case Kpgdown:
- kbscroll(+40);
- break;
- case Kpgup:
- kbscroll(-40);
- break;
- default:
- kbadd(e.kbdc);
- break;
- }
- break;
-
- case Emouse:
- if(e.mouse.buttons&1)
- mselect(e.mouse.xy);
- if(e.mouse.buttons&4)
- goto End;
- if(e.mouse.buttons&8)
- kbscroll(-40);
- if(e.mouse.buttons&16)
- kbscroll(+40);
- break;
- }
- }
-End:
- if(nmatches > 0)
- print("%s\n", matches[selected]);- exits(nil);
-}
--- a/mkfile
+++ b/mkfile
@@ -1,16 +1,9 @@
</$objtype/mkfile
-TARG=\
- line\
-
+TARG= dmenu
HFILES=
-
+OFILES= dmenu.$O
LIB= /$objtype/lib/libdraw.a
-BIN= /$objtype/bin/sel
+BIN= /$objtype/bin
-</sys/src/cmd/mkmany
-
-install: $BIN
-
-$BIN:
- mkdir -p $target
+</sys/src/cmd/mkone
--
⑨