commit - d29c160f7129fc8f3ecb23638648704792d42929
commit + 124df174f78190c79ad0bffaeff238e585457f4c
blob - be5b28412e99f7a59d3a5659ebb5813336b09f97
blob + 70485948562d17a7171533ec4f1137a62ddad7e9
--- mymenu.c
+++ mymenu.c
#endif
};
-// A simple linked list to store the completions.
struct completion {
char *completion;
char *rcompletion;
- struct completion *next;
};
// Wrap the linked list of completions
struct completions {
struct completion *completions;
- int selected;
- int lenght;
+ ssize_t selected;
+ size_t lenght;
};
// return a newly allocated (and empty) completion list
-struct completions *compls_new() {
+struct completions *compls_new(size_t lenght) {
struct completions *cs = malloc(sizeof(struct completions));
if (cs == nil)
return cs;
- cs->completions = nil;
+ cs->completions = calloc(lenght, sizeof(struct completion));
cs->selected = -1;
- cs->lenght = 0;
+ cs->lenght = lenght;
return cs;
}
-// Return a newly allocated (and empty) completion
-struct completion *compl_new() {
- struct completion *c = malloc(sizeof(struct completion));
- if (c == nil)
- return c;
-
- c->completion = nil;
- c->rcompletion = nil;
- c->next = nil;
- return c;
-}
-
-// delete ONLY the given completion (i.e. does not free c->next...)
-void compl_delete(struct completion *c) {
- free(c);
-}
-
-// delete the current completion and the next (c->next) and so on...
-void compl_delete_rec(struct completion *c) {
- while (c != nil) {
- struct completion *t = c->next;
- free(c);
- c = t;
- }
-}
-
// Delete the wrapper and the whole list
void compls_delete(struct completions *cs) {
if (cs == nil)
return;
- compl_delete_rec(cs->completions);
+ free(cs->completions);
free(cs);
}
// completions (null terminated). Expects a non-null `cs'. lines and
// vlines should have the same lenght OR vlines is null
void filter(struct completions *cs, char *text, char **lines, char **vlines) {
- struct completion *c = compl_new();
- if (c == nil) {
- return;
- }
+ size_t index = 0;
+ size_t matching = 0;
- cs->completions = c;
-
- int index = 0;
- int matching = 0;
-
if (vlines == nil)
vlines = lines;
while (true) {
- char *l = vlines[index] ? vlines[index] : lines[index];
+ char *l = vlines[index] != nil ? vlines[index] : lines[index];
if (l == nil)
break;
if (strcasestr(l, text) != nil) {
+ struct completion *c = &cs->completions[matching];
+ c->completion = l;
+ c->rcompletion = lines[index];
matching++;
-
- c->next = compl_new();
- c = c->next;
- if (c == nil) {
- compls_delete(cs);
- return;
- }
- c->completion = l;
- c->rcompletion = lines[index];
}
index++;
}
-
- struct completion *f = cs->completions->next;
- compl_delete(cs->completions);
- cs->completions = f;
cs->lenght = matching;
cs->selected = -1;
}
// update the given completion, that is: clean the old cs & generate a new one.
void update_completions(struct completions *cs, char *text, char **lines, char **vlines, bool first_selected) {
- compl_delete_rec(cs->completions);
filter(cs, text, lines, vlines);
if (first_selected && cs->lenght > 0)
cs->selected = 0;
index = 0;
index = cs->selected = (cs->lenght + (p ? index - 1 : index + 1)) % cs->lenght;
- struct completion *n = cs->completions;
+ struct completion *n = &cs->completions[cs->selected];
- // find the selected item
- while (index != 0) {
- index--;
- n = n->next;
- }
-
free(*text);
*text = strdup(n->completion);
if (text == nil) {
// `realloc(3)` to store more line. Return the number of lines
// read. The last item will always be a NULL pointer. It ignore the
// "null" (empty) lines
-int readlines(char ***lns, int items) {
- int n = 0;
+size_t readlines(char ***lns, size_t items) {
+ size_t n = 0;
char **lines = *lns;
while (true) {
size_t linelen = 0;
#ifdef USE_XFT
XGlyphInfo gi;
XftTextExtentsUtf8(r->d, r->font, str, len, &gi);
- /* height = gi.height; */
- /* 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
XFillRectangle(r->d, r->w, r->completion_bg, start_at, r->y_zero, r->width, inner_height(r));
- struct completion *c = cs->completions;
- for (int i = 0; c != nil; ++i) {
- enum text_type tt = cs->selected == i ? COMPL_HIGH : COMPL;
- GC h = cs->selected == i ? r->completion_highlighted_bg : r->completion_bg;
+ for (size_t i = 0; i < cs->lenght; ++i) {
+ struct completion *c = &cs->completions[i];
+ enum text_type tt = cs->selected == (ssize_t)i ? COMPL_HIGH : COMPL;
+ GC h = cs->selected == (ssize_t)i ? r->completion_highlighted_bg : r->completion_bg;
+
int len = strlen(c->completion);
int text_width = text_extents(c->completion, len, r, nil, nil);
if (start_at > inner_width(r))
break; // don't draw completion if the space isn't enough
-
- c = c->next;
}
}
start_at += r->y_zero;
- struct completion *c = cs->completions;
- for (int i = 0; c != nil; ++i){
- enum text_type tt = cs->selected == i ? COMPL_HIGH : COMPL;
- GC h = cs->selected == i ? r->completion_highlighted_bg : r->completion_bg;
+ for (size_t i = 0; i < cs->lenght; ++i){
+ struct completion *c = &cs->completions[i];
+ enum text_type tt = cs->selected == (ssize_t)i ? COMPL_HIGH : COMPL;
+ GC h = cs->selected == (ssize_t)i ? r->completion_highlighted_bg : r->completion_bg;
int len = strlen(c->completion);
text_extents(c->completion, len, r, &width, &height);
if (start_at > inner_height(r))
break; // don't draw completion if the space isn't enough
-
- c = c->next;
}
}
// read the lines from stdin
char **lines = calloc(INITIAL_ITEMS, sizeof(char*));
check_allocation(lines);
- int nlines = readlines(&lines, INITIAL_ITEMS);
+ size_t nlines = readlines(&lines, INITIAL_ITEMS);
char **vlines = nil;
if (sep != nil) {
int l = strlen(sep);
check_allocation(text);
/* struct completions *cs = filter(text, lines); */
- struct completions *cs = compls_new();
+ struct completions *cs = compls_new(nlines);
check_allocation(cs);
// start talking to xorg
while (true) {
if (index == 0)
break;
- c = c->next;
+ c++;
index--;
}
char *t = c->rcompletion;