diff --git a/dat.h b/dat.h index 2dcbc69..876adb8 100644 --- a/dat.h +++ b/dat.h @@ -28,7 +28,7 @@ enum Maxkouho = 32, Maxdisp = 9, Imgw = (Maxrunes + 3) * Fontsz, - Imgh = (Maxdisp + 1) * Fontsz, + Imgh = (Maxdisp + 2) * Fontsz, Colfg = 0x000000, Colbg = 0xffffff, @@ -132,6 +132,8 @@ struct Drawcmd Str kouho[Maxdisp]; int nkouho; int sel; + int first; + int total; Caret caret; }; diff --git a/fn.h b/fn.h index 30605ab..d212b26 100644 --- a/fn.h +++ b/fn.h @@ -29,6 +29,7 @@ void dictlookup(Dictreq*, Dictres*); void drawthread(void*); void popupposition(Caret*, int, int, int, int, int, int, int*, int*); +int pagemarker(char*, int, int, int, int); void imthread(void*); Emit transmap(Im*, Rune); Emit transko(Im*, Rune); diff --git a/popup_layout.c b/popup_layout.c index fc7bfff..856f6a9 100644 --- a/popup_layout.c +++ b/popup_layout.c @@ -1,6 +1,18 @@ #include "dat.h" #include "fn.h" +int +pagemarker(char *buf, int nbuf, int first, int shown, int total) +{ + if(nbuf <= 0) + return 0; + buf[0] = 0; + if(total <= Maxdisp || shown <= 0) + return 0; + return snprint(buf, nbuf, "%d-%d/%d", first + 1, + first + shown, total); +} + void popupposition(Caret *caret, int pointerx, int pointery, int screenw, int screenh, int w, int h, int *x, int *y) diff --git a/strans.c b/strans.c index e75ee61..60c45e6 100644 --- a/strans.c +++ b/strans.c @@ -176,6 +176,8 @@ show(void) if(n > Maxdisp) n = Maxdisp; dc.nkouho = n; dc.sel = im.sel >= 0 ? im.sel - first : -1; + dc.first = first; + dc.total = im.nkouho; dc.caret = caret; for(i = 0; i < n; i++) dc.kouho[i] = im.kouho[first + i]; diff --git a/tests/engine_test.c b/tests/engine_test.c index 6e5e4f3..8d17391 100644 --- a/tests/engine_test.c +++ b/tests/engine_test.c @@ -694,7 +694,9 @@ checkcandidatepage(struct ct *t, char *where, int first, int n, int sel) show(); if(!CT_CHECK(t, draindraw(&dc) > 0)) return 0; - if(!CT_EQ_INT(t, n, dc.nkouho) || !CT_EQ_INT(t, sel, dc.sel)) + if(!CT_EQ_INT(t, n, dc.nkouho) || !CT_EQ_INT(t, sel, dc.sel) || + !CT_EQ_INT(t, first, dc.first) || + !CT_EQ_INT(t, im.nkouho, dc.total)) return 0; if(n == 0) return 1; @@ -705,6 +707,50 @@ checkcandidatepage(struct ct *t, char *where, int first, int n, int sel) return checkstr(t, where, want, &dc.kouho[n-1]); } +void +engine_candidate_page_metadata(struct ct *t) +{ + static const struct { + int total; + int sel; + int first; + int shown; + int local; + } cases[] = { + { 9, 8, 0, 9, 8 }, + { 10, 8, 0, 9, 8 }, + { 10, 9, 9, 1, 0 }, + { 18, 8, 0, 9, 8 }, + { 18, 17, 9, 9, 8 }, + { 32, 8, 0, 9, 8 }, + { 32, 17, 9, 9, 8 }, + { 32, 26, 18, 9, 8 }, + { 32, 31, 27, 5, 4 }, + }; + Drawcmd dc; + int i; + + /* A clearing draw is the observable zero-candidate snapshot. */ + candidatebegin(1); + show(); + draindraw(nil); + setcandidates(0); + show(); + if(CT_CHECK(t, draindraw(&dc) > 0)){ + CT_EQ_INT(t, 0, dc.nkouho); + CT_EQ_INT(t, -1, dc.sel); + CT_EQ_INT(t, 0, dc.first); + CT_EQ_INT(t, 0, dc.total); + } + + for(i = 0; i < nelem(cases); i++){ + candidatebegin(cases[i].total); + im.sel = cases[i].sel; + checkcandidatepage(t, "candidate page metadata", + cases[i].first, cases[i].shown, cases[i].local); + } +} + void engine_candidate_page_snapshots(struct ct *t) { diff --git a/tests/popup_test.c b/tests/popup_test.c index 6923b66..08df9bf 100644 --- a/tests/popup_test.c +++ b/tests/popup_test.c @@ -4,8 +4,33 @@ void popup_layout(struct ct *t) { + static const struct { + int first; + int shown; + int total; + char *want; + } markers[] = { + { 0, 0, 0, "" }, + { 0, 9, 9, "" }, + { 0, 9, 10, "1-9/10" }, + { 9, 1, 10, "10-10/10" }, + { 0, 9, 18, "1-9/18" }, + { 9, 9, 18, "10-18/18" }, + { 9, 9, 32, "10-18/32" }, + { 18, 9, 32, "19-27/32" }, + { 27, 5, 32, "28-32/32" }, + }; + char buf[32]; Caret caret; - int x, y; + int i, n, x, y; + + for(i = 0; i < nelem(markers); i++){ + n = pagemarker(buf, sizeof buf, markers[i].first, + markers[i].shown, markers[i].total); + CT_EQ_INT(t, strlen(markers[i].want), n); + CT_CHECK(t, strcmp(markers[i].want, buf) == 0); + } + CT_EQ_INT(t, (1 + Maxdisp + 1) * Fontsz, Imgh); memset(&caret, 0, sizeof caret); popupposition(&caret, 40, 50, 800, 600, 100, 60, &x, &y); diff --git a/tests/test.h b/tests/test.h index 59190b0..c947085 100644 --- a/tests/test.h +++ b/tests/test.h @@ -32,6 +32,7 @@ void engine_clears_candidates(struct ct*); void engine_backspace_clears_candidates(struct ct*); void engine_selects_visible_candidate(struct ct*); void engine_candidate_shortcut_modifiers(struct ct*); +void engine_candidate_page_metadata(struct ct*); void engine_candidate_page_snapshots(struct ct*); void engine_candidate_page_movement(struct ct*); void engine_candidate_completion(struct ct*); diff --git a/tests/unit_test.c b/tests/unit_test.c index 76f057b..562d393 100644 --- a/tests/unit_test.c +++ b/tests/unit_test.c @@ -86,6 +86,7 @@ static const struct ct_test tests[] = { { "engine/backspace-clears-candidates", engine_backspace_clears_candidates }, { "engine/selects-visible-candidate", engine_selects_visible_candidate }, { "engine/candidate-shortcut-modifiers", engine_candidate_shortcut_modifiers }, + { "engine/candidate-page-metadata", engine_candidate_page_metadata }, { "engine/candidate-page-snapshots", engine_candidate_page_snapshots }, { "engine/candidate-page-movement", engine_candidate_page_movement }, { "engine/candidate-completion", engine_candidate_completion }, diff --git a/win.c b/win.c index baf30b6..ba7a9f2 100644 --- a/win.c +++ b/win.c @@ -158,8 +158,9 @@ fill(u32int *buf, int n, u32int color) static void drawkouho(Drawcmd *dc, int n, int w, int h) { - int npre, sely, y, i; - Str num, *s; + char buf[32]; + int nmark, npre, sely, y, i; + Str mark, num, *s; if(w <= 0 || w > Imgw || h <= 0 || h > Imgh) return; @@ -178,6 +179,11 @@ drawkouho(Drawcmd *dc, int n, int w, int h) textdraw(img, w, h, 0, y, &num); textdrawfit(img, w, h, 2*Fontsz, y, w - 2*Fontsz, s); } + nmark = pagemarker(buf, sizeof buf, dc->first, n, dc->total); + if(nmark != 0){ + sinit(&mark, buf, nmark); + textdraw(img, w, h, 0, y, &mark); + } } static void @@ -201,8 +207,10 @@ winhide(void) static int winshow(Drawcmd *dc) { + char buf[32]; vlong width; - int npre, px, py, w, h, i, n, maxw; + int nmark, npre, px, py, w, h, i, n, maxw; + Str mark; u32int vals[4]; xcb_query_pointer_reply_t *ptr; xcb_query_pointer_cookie_t cookie; @@ -215,7 +223,12 @@ winshow(Drawcmd *dc) maxw = textwidth(&dc->pre); for(i = 0; i < n; i++) maxw = max(maxw, textwidth(&dc->kouho[i])); - vals[3] = h = (n + npre) * Fontsz; + nmark = pagemarker(buf, sizeof buf, dc->first, n, dc->total); + if(nmark != 0){ + sinit(&mark, buf, nmark); + maxw = max(maxw, textwidth(&mark)); + } + vals[3] = h = (n + npre + (nmark != 0)) * Fontsz; width = (vlong)maxw + 3*Fontsz; vals[2] = w = min(min(max(width, 1), Imgw), scr->width_in_pixels); if(w <= 0 || w > Imgw || h <= 0 || h > Imgh)