From: ewt Date: Wed, 29 Jan 1997 21:02:37 +0000 (+0000) Subject: incorporated rewrite from Elliot Lee X-Git-Tag: v0-9~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a61e44cc57505495e286de7b207be3d08338f308;p=thirdparty%2Fnewt.git incorporated rewrite from Elliot Lee --- diff --git a/listbox.c b/listbox.c index a80c1e0..b8a2718 100644 --- a/listbox.c +++ b/listbox.c @@ -1,3 +1,5 @@ +/* This goofed-up box whacked into shape by Elliot Lee */ + #include #include #include @@ -5,12 +7,25 @@ #include "newt.h" #include "newt_pr.h" + +/* Linked list of items in the listbox */ +struct items { + void *key, *data; + struct items *next; +}; + +/* Holds all the relevant information for this listbox */ struct listbox { - newtComponent * items, form; - int numItems; - int allocedItems; - int flags; - newtComponent sb; + newtComponent sb; /* Scrollbar on right side of listbox */ + int numItems, curWidth; + int currItem, startShowItem; /* startShowItem is the first item displayed + on the screen */ + int isActive; /* If we handle key events all the time, it seems + to do things even when they are supposed to be for + another button/whatever */ + struct items *boxItems; + int flags; /* flags for this listbox, right now just + NEWT_LISTBOX_RETURNEXIT */ }; static void listboxDraw(newtComponent co); @@ -21,38 +36,39 @@ static struct componentOps listboxOps = { listboxDraw, listboxEvent, listboxDestroy, -} ; +}; newtComponent newtListbox(int left, int top, int height, int flags) { newtComponent co, sb; struct listbox * li; - co = malloc(sizeof(*co)); - li = malloc(sizeof(struct listbox)); + if (!(co = malloc(sizeof(*co)))) + return NULL; - li->allocedItems = 5; - li->numItems = 0; - li->flags = flags; - li->items = malloc(li->allocedItems * sizeof(*li->items)); + if (!(li = malloc(sizeof(struct listbox)))) { + free(co); + return NULL; + } + + li->boxItems = NULL; + li->numItems = 0; + li->currItem = 0; + li->isActive = 0; + li->startShowItem = 0; + li->flags = flags & (NEWT_LISTBOX_RETURNEXIT); if (height) sb = newtVerticalScrollbar(left, top, height, COLORSET_LISTBOX, COLORSET_ACTLISTBOX); else sb = NULL; - li->form = newtForm(sb, NULL, NEWT_FORM_NOF12); - li->sb = sb; - - if (height) { - newtFormSetHeight(li->form, height); - newtFormAddComponent(li->form, sb); - } + li->sb = sb; co->data = li; co->left = left; co->top = top; - co->height = li->form->height; - co->width = li->form->width; + co->height = height; + li->curWidth = 5; co->ops = &listboxOps; co->takesFocus = 1; @@ -61,90 +77,331 @@ newtComponent newtListbox(int left, int top, int height, int flags) { void newtListboxSetCurrent(newtComponent co, int num) { struct listbox * li = co->data; + if (num >= li->numItems) + li->currItem = li->numItems - 1; + else if (num < 0) + li->currItem = 0; + else + li->currItem = num; + + if (li->currItem < li->startShowItem) + li->startShowItem = li->currItem; + else if (li->currItem - li->startShowItem > co->height - 1) + li->startShowItem = li->currItem - co->height + 1; + if (li->startShowItem + co->height > li->numItems) + li->startShowItem = li->numItems - co->height; - newtFormSetCurrent(li->form, li->items[num]); + newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); + listboxDraw(co); } void * newtListboxGetCurrent(newtComponent co) { struct listbox * li = co->data; - newtComponent curr; int i; + struct items *item; - /* Having to do this linearly is really, really dumb */ + for(i = 0, item = li->boxItems; item != NULL && i < li->currItem; + i++, item = item->next); - curr = newtFormGetCurrent(li->form); - for (i = 0; i < li->numItems; i++) { - if (li->items[i] == curr) break; - } - - if (li->items[i] == curr) - return newtListitemGetData(li->items[i]); + if (item) + return item->data; else return NULL; } +void newtListboxSetText(newtComponent co, int num, char * text) { + struct listbox * li = co->data; + int i; + struct items *item; + + for(i = 0, item = li->boxItems; item != NULL && i < num; + i++, item = item->next); + + if(!item) + return; + else + item->key = text; + + if (strlen(text) > li->curWidth) { + co->width = li->curWidth = strlen(text); + if (li->sb) + li->sb->left = co->left + co->width + 1; + } + + if (num >= li->startShowItem && num <= li->startShowItem + co->height) + listboxDraw(co); +} + void newtListboxSetEntry(newtComponent co, int num, char * text) { + newtListboxSetText(co, num, text); +} + +void newtListboxSetData(newtComponent co, int num, void * data) { struct listbox * li = co->data; + int i; + struct items *item; - /* this won't increase the size of the listbox! */ + for(i = 0, item = li->boxItems; item != NULL && i < num; + i++, item = item->next); - newtListitemSet(li->items[num], text); - co->ops->draw(co); + item->data = data; } -void newtListboxAddEntry(newtComponent co, char * text, void * data) { +int newtListboxAddEntry(newtComponent co, char * text, void * data) { struct listbox * li = co->data; + struct items *item; + + if(li->boxItems) { + for (item = li->boxItems; item->next != NULL; item = item->next); - if (li->numItems == li->allocedItems) { - li->allocedItems += 5; - li->items = realloc(li->items, li->allocedItems * sizeof(*li->items)); + item = item->next = malloc(sizeof(struct items)); + } else { + item = li->boxItems = malloc(sizeof(struct items)); } - if (li->numItems) - li->items[li->numItems] = newtListitem(co->left, - li->numItems + co->top, - text, 0, - li->items[li->numItems - 1], - data); - else - li->items[li->numItems] = newtListitem(co->left, - li->numItems + co->top, - text, 0, NULL, data); + if (text && (strlen(text) > li->curWidth)) + li->curWidth = strlen(text); + + item->key = text; item->data = data; item->next = NULL; - newtFormAddComponent(li->form, li->items[li->numItems]); + if (li->sb) + li->sb->left = co->left + li->curWidth + 1; + + co->width = li->curWidth; li->numItems++; + listboxDraw(co); + + return li->numItems; +} + + +int newtListboxInsertEntry(newtComponent co, char * text, void * data, + int num) { + struct listbox * li = co->data; + struct items *item, *t; + int i; - co->height = li->form->height; - co->width = li->form->width; + if (li->boxItems) { + for(i = 0, item = li->boxItems; item->next != NULL && i < num; + item = item->next, i++); + + t = item->next; + item = item->next = malloc(sizeof(struct items)); + item->next = t; + } else { + item = li->boxItems = malloc(sizeof(struct items)); + item->next = NULL; + } + + if (text && (strlen(text) > li->curWidth)) + li->curWidth = strlen(text); + + item->key = text; item->data = data; if (li->sb) - li->sb->left = co->left + co->width; + li->sb->left = co->left + li->curWidth + 1; + + co->width = li->curWidth; + li->numItems++; + listboxDraw(co); + + return li->numItems; } -static void listboxDraw(newtComponent co) { +int newtListboxDeleteEntry(newtComponent co, int num) { struct listbox * li = co->data; + int i, widest = 0, t; + struct items *item, *item2; + + if (!li->boxItems) + return -1; + + if (num <= 0) { + item = li->boxItems; + li->boxItems = item->next; + + /* Fix things up for the width-finding loop near the bottom */ + item2 = li->boxItems; + widest = strlen(item2->key); + } else { + for(i = 0, item = li->boxItems; item != NULL && i != li->currItem; + i++, item = item->next) { + if((t = strlen(item->key)) > widest) widest = t; + item2 = item; + } + + if (!item) + return -1; + + item2->next = item->next; + } + + free(item); + li->numItems--; + + for (item = item2->next; item != NULL; item = item->next) + if((t = strlen(item->key)) > widest) widest = t; + + /* Adjust the listbox width */ + co->width = li->curWidth = widest; + if (li->sb) + li->sb->left = co->left + widest + 1; + + listboxDraw(co); - li->form->ops->draw(li->form); + return li->numItems; } -static struct eventResult listboxEvent(newtComponent co, struct event ev) { +/* If you don't want to get back the text, pass in NULL for the ptr-ptr. Same + goes for the data. */ +void newtListboxGetEntry(newtComponent co, int num, char **text, void **data) { struct listbox * li = co->data; + int i; + struct items *item; + + if (!li->boxItems || num >= li->numItems) { + if(text) + *text = NULL; + if(data) + *data = NULL; + return; + } + + i = 0; + item = li->boxItems; + while (item && i < num) { + i++, item = item->next; + } + + if (item) { + if (text) + *text = item->key; + if (data) + *data = item->data; + } +} + +static void listboxDraw(newtComponent co) +{ + struct listbox * li = co->data; + struct items *item; + int i, j; + + SLsmg_set_color(NEWT_COLORSET_LISTBOX); + + if(li->sb) + li->sb->ops->draw(li->sb); + + for(i = 0, item = li->boxItems; item != NULL && i < li->startShowItem; + i++, item = item->next); + + j = i; + newtGotorc(co->top - 1, co->left); + + for (i = 0; item != NULL && i < co->height; i++, item = item->next) { + if (!item->key) continue; + + newtGotorc(co->top + i, co->left + 1); + if(j + i == li->currItem) + SLsmg_set_color(NEWT_COLORSET_ACTLISTBOX); + + SLsmg_write_nstring(item->key, li->curWidth); + + if(j + i == li->currItem) + SLsmg_set_color(NEWT_COLORSET_LISTBOX); + } +} + +static struct eventResult listboxEvent(newtComponent co, struct event ev) { struct eventResult er; + struct listbox * li = co->data; - if ((li->flags & NEWT_LISTBOX_RETURNEXIT) && ev.when == EV_NORMAL && - ev.event == EV_KEYPRESS && ev.u.key == '\r') { - er.result = ER_EXITFORM; - return er; + er.result = ER_IGNORED; + + switch(ev.event) { + case EV_KEYPRESS: + if (!li->isActive) break; + + switch(ev.u.key) { + case NEWT_KEY_ENTER: + if(li-> flags & NEWT_LISTBOX_RETURNEXIT) + er.result = ER_EXITFORM; + break; + + case NEWT_KEY_UP: + if(li->currItem > 0) { + li->currItem--; + if(li->currItem < li->startShowItem) + li->startShowItem = li->currItem; + listboxDraw(co); + } + + newtGotorc(co->top + li->currItem - li->startShowItem, + co->left); + newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); + er.result = ER_SWALLOWED; + break; + + case NEWT_KEY_DOWN: + if(li->currItem < li->numItems - 1) { + li->currItem++; + if(li->currItem > (li->startShowItem + co->height - 1)) { + li->startShowItem = li->currItem - co->height + 1; + if(li->startShowItem + co->height > li->numItems) + li->startShowItem = li->numItems - co->height; + } + listboxDraw(co); + } + + newtGotorc(co->top + li->currItem - li->startShowItem, + co->left); + newtScrollbarSet(li->sb, li->currItem + 1, li->numItems); + er.result = ER_SWALLOWED; + break; + + case NEWT_KEY_PGUP: + newtListboxSetCurrent(co, li->currItem - co->height + 1); + er.result = ER_SWALLOWED; + break; + + case NEWT_KEY_PGDN: + newtListboxSetCurrent(co, li->currItem + co->height - 1); + er.result = ER_SWALLOWED; + break; + + default: + /* keeps gcc quiet */ + } + break; + + case EV_FOCUS: + newtGotorc(co->top + li->currItem - li->startShowItem, co->left); + li->isActive = 1; + er.result = ER_SWALLOWED; + break; + + case EV_UNFOCUS: + li->isActive = 0; + er.result = ER_SWALLOWED; + break; } - return li->form->ops->event(li->form, ev); + return er; } static void listboxDestroy(newtComponent co) { struct listbox * li = co->data; + struct items * item, * nextitem; + + nextitem = item = li->boxItems; + + while (item != NULL) { + nextitem = item->next; + free(item); + item = nextitem; + } - li->form->ops->destroy(li->form); - free(li->items); free(li); free(co); } +