commit e5186d6b0b82449e564049bb3ddc13face30c606 from: Omar Polo date: Sat May 26 07:47:38 2018 UTC Added customizable padding + vertical alignment fixes commit - fa5a6135a8a93244a1fa23746bbcfb6b9d8d0c17 commit + e5186d6b0b82449e564049bb3ddc13face30c606 blob - 875dc80f18b234350303bf0c4c30b3e62c55e347 blob + 33acdd45ef8d27c1bd3ad2ebc89e316c4541f682 --- mymenu.1 +++ mymenu.1 @@ -47,8 +47,15 @@ could be supplied. In addition to it, the special valu be used: in that case the window will be centered on the x axes. .It MyMenu.y The Y coordinate of the topmost left corner of the window. Like the X -coordinate, pixel dimension, percentage dimension and the special +coordinate a pixel dimension, percentage dimension or the special value "middle" could be supplied. +.It MyMenu.padding +Change the padding. In the horizontal layout the padding is the space +between the rectangle of the completion and the text as well as the +space between the prompt and the first completion. In the horizontal +layout the padding is the horizontal spacing between the window edge +and the text as well as the space up and down the text within the +completion. The default value is 10. .It MyMenu.prompt.background The background of the prompt. .It MyMenu.prompt.foreground blob - cd1d7f801a6e8ab04ab6a245e4266b717141b1bf blob + b744f0b7bc36f67ad1d1a2941f783cba0de606b9 --- mymenu.c +++ mymenu.c @@ -84,6 +84,12 @@ enum text_type {PROMPT, COMPL, COMPL_HIGH}; struct rendering { Display *d; Window w; + int width; + int height; + int padding; + bool horizontal_layout; + char *ps1; + int ps1len; GC prompt; GC prompt_bg; GC completion; @@ -91,19 +97,14 @@ struct rendering { GC completion_highlighted; GC completion_highlighted_bg; #ifdef USE_XFT + XftFont *font; XftDraw *xftdraw; XftColor xft_prompt; XftColor xft_completion; XftColor xft_completion_highlighted; - XftFont *font; #else XFontSet *font; #endif - int width; - int height; - bool horizontal_layout; - char *ps1; - int ps1len; }; struct completions { @@ -364,10 +365,10 @@ int text_extents(char *str, int len, struct rendering #ifdef USE_XFT XGlyphInfo gi; XftTextExtentsUtf8(r->d, r->font, str, len, &gi); - // Honestly I don't know why this won't work, but I found that this - // formula seems to work with various ttf font /* height = gi.height; */ - height = (gi.height + (r->font->ascent - r->font->descent)/2) / 2; + /* height = (gi.height + (r->font->ascent - r->font->descent)/2) / 2; */ + /* height = (r->font->ascent - r->font->descent)/2 + gi.height*2; */ + height = r->font->ascent - r->font->descent; width = gi.width - gi.x; #else XRectangle rect; @@ -420,19 +421,20 @@ char *strdupn(char *str) { // | 20 char text | completion | completion | completion | compl | // |------------------|----------------------------------------------| void draw_horizontally(struct rendering *r, char *text, struct completions *cs) { - // TODO: make these dynamic? int prompt_width = 20; // char - int padding = 10; int width, height; char *ps1_dup = strdupn(r->ps1); + if (ps1_dup == nil) + return; + ps1_dup = ps1_dup == nil ? r->ps1 : ps1_dup; int ps1xlen = text_extents(ps1_dup, r->ps1len, r, &width, &height); free(ps1_dup); int start_at = ps1xlen; start_at = text_extents("n", 1, r, nil, nil); - start_at = start_at * prompt_width + padding; + start_at = start_at * prompt_width + r->padding; int texty = (height + r->height) >>1; @@ -441,8 +443,8 @@ void draw_horizontally(struct rendering *r, char *text int text_len = strlen(text); if (text_len > prompt_width) text = text + (text_len - prompt_width); - draw_string(r->ps1, r->ps1len, padding, texty, r, PROMPT); - draw_string(text, MIN(text_len, prompt_width), padding + ps1xlen, texty, r, PROMPT); + draw_string(r->ps1, r->ps1len, r->padding, texty, r, PROMPT); + draw_string(text, MIN(text_len, prompt_width), r->padding + ps1xlen, texty, r, PROMPT); XFillRectangle(r->d, r->w, r->completion_bg, start_at, 0, r->width, r->height); @@ -453,11 +455,11 @@ void draw_horizontally(struct rendering *r, char *text int len = strlen(cs->completion); int text_width = text_extents(cs->completion, len, r, nil, nil); - XFillRectangle(r->d, r->w, h, start_at, 0, text_width + padding*2, r->height); + XFillRectangle(r->d, r->w, h, start_at, 0, text_width + r->padding*2, r->height); - draw_string(cs->completion, len, start_at + padding, texty, r, tt); + draw_string(cs->completion, len, start_at + r->padding, texty, r, tt); - start_at += text_width + padding * 2; + start_at += text_width + r->padding * 2; if (start_at > r->width) break; // don't draw completion if the space isn't enough @@ -475,15 +477,10 @@ void draw_horizontally(struct rendering *r, char *text // |-----------------------------------------------------------------| // | completion | // |-----------------------------------------------------------------| -// TODO: dunno why but in the call to Xutf8DrawString, by logic, -// should be padding and not padding*2, but the text doesn't seem to -// be vertically centered otherwise.... -void draw_vertically(struct rendering *r, char *text, struct completions *cs) { - int padding = 10; // TODO make this dynamic - +void draw_vertically(struct rendering *r, char *text, struct completions *cs) { int height, width; - text_extents("fjpgl", 5, r, &width, &height); - int start_at = height + padding*2; + text_extents("fjpgl", 5, r, nil, &height); + int start_at = height + r->padding; XFillRectangle(r->d, r->w, r->completion_bg, 0, 0, r->width, r->height); XFillRectangle(r->d, r->w, r->prompt_bg, 0, 0, r->width, start_at); @@ -493,8 +490,9 @@ void draw_vertically(struct rendering *r, char *text, int ps1xlen = text_extents(ps1_dup, r->ps1len, r, nil, nil); free(ps1_dup); - draw_string(r->ps1, r->ps1len, padding, padding*2, r, PROMPT); - draw_string(text, strlen(text), padding + ps1xlen, padding*2, r, PROMPT); + draw_string(r->ps1, r->ps1len, r->padding, height + r->padding, r, PROMPT); + draw_string(text, strlen(text), r->padding + ps1xlen, height + r->padding, r, PROMPT); + start_at += r->padding; while (cs != nil) { enum text_type tt = cs->selected ? COMPL_HIGH : COMPL; @@ -502,10 +500,10 @@ void draw_vertically(struct rendering *r, char *text, int len = strlen(cs->completion); text_extents(cs->completion, len, r, &width, &height); - XFillRectangle(r->d, r->w, h, 0, start_at, r->width, height + padding*2); - draw_string(cs->completion, len, padding, start_at + padding*2, r, tt); + XFillRectangle(r->d, r->w, h, 0, start_at, r->width, height + r->padding*2); + draw_string(cs->completion, len, r->padding, start_at + height + r->padding, r, tt); - start_at += height + padding *2; + start_at += height + r->padding *2; if (start_at > r->height) break; // don't draw completion if the space isn't enough @@ -676,6 +674,8 @@ int main() { int x = 0; int y = 0; + int padding = 10; + char *ps1 = strdup("$ "); check_allocation(ps1); @@ -793,13 +793,18 @@ int main() { if (XrmGetResource(xdb, "MyMenu.x", "*", datatype, &value) == true) x = parse_int_with_middle(value.addr, x, d_width, width); else - fprintf(stderr, "no x defined, using %d\n", width); + fprintf(stderr, "no x defined, using %d\n", x); if (XrmGetResource(xdb, "MyMenu.y", "*", datatype, &value) == true) y = parse_int_with_middle(value.addr, y, d_height, height); else - fprintf(stderr, "no y defined, using %d\n", height); + fprintf(stderr, "no y defined, using %d\n", y); + if (XrmGetResource(xdb, "MyMenu.padding", "*", datatype, &value) == true) + padding = parse_integer(value.addr, padding); + else + fprintf(stderr, "no y defined, using %d\n", padding); + XColor tmp; // TODO: tmp needs to be free'd after every allocation? @@ -921,6 +926,7 @@ int main() { .completion_highlighted_bg = XCreateGC(d, w, 0, &values), .width = width, .height = height, + .padding = padding, .horizontal_layout = horizontal_layout, .ps1 = ps1, .ps1len = strlen(ps1)