server/core/src/util/listbox.c

219 lines
5.2 KiB
C
Raw Normal View History

2010-08-08 10:06:34 +02:00
/* vi: set ts=2:
* +-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
* | | Enno Rehling <enno@eressea.de>
* | Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
* | (c) 1998 - 2006 |
* | | This program may not be used, modified or distributed
* +-------------------+ without prior permission by the authors of Eressea.
*
*/
/* wenn platform.h nicht vor curses included wird, kompiliert es unter windows nicht */
#include <platform.h>
#include <kernel/config.h>
2010-08-08 10:06:34 +02:00
#undef bool
#include <curses.h>
#include <util/bool.h>
2010-08-08 10:06:34 +02:00
#include "listbox.h"
2010-09-12 05:11:15 +02:00
#include "gmtool_structs.h"
2010-08-08 10:06:34 +02:00
#include <util/log.h>
2010-08-08 10:06:34 +02:00
#include <string.h>
#include <ctype.h>
void
2011-03-07 08:02:35 +01:00
insert_selection(list_selection ** p_sel, list_selection * prev,
const char *str, void *payload)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
list_selection *sel = calloc(sizeof(list_selection), 1);
2010-08-08 10:06:34 +02:00
sel->str = strdup(str);
sel->data = payload;
if (*p_sel) {
2011-03-07 08:02:35 +01:00
list_selection *s;
2010-08-08 10:06:34 +02:00
sel->next = *p_sel;
sel->prev = sel->next->prev;
2011-03-07 08:02:35 +01:00
sel->next->prev = sel;
2010-08-08 10:06:34 +02:00
if (sel->prev) {
sel->prev->next = sel;
2011-03-07 08:02:35 +01:00
sel->index = sel->prev->index + 1;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
for (s = sel->next; s; s = s->next) {
s->index = s->prev->index + 1;
2010-08-08 10:06:34 +02:00
}
*p_sel = sel;
} else {
*p_sel = sel;
sel->prev = prev;
2011-03-07 08:02:35 +01:00
if (prev)
sel->index = prev->index + 1;
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
list_selection **push_selection(list_selection ** p_sel, char *str,
void *payload)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
list_selection *sel = calloc(sizeof(list_selection), 1);
list_selection *prev = NULL;
2010-08-08 10:06:34 +02:00
sel->str = str;
sel->data = payload;
while (*p_sel) {
prev = *p_sel;
2011-03-07 08:02:35 +01:00
p_sel = &prev->next;
2010-08-08 10:06:34 +02:00
}
*p_sel = sel;
if (prev) {
sel->prev = prev;
2011-03-07 08:02:35 +01:00
sel->index = prev->index + 1;
2010-08-08 10:06:34 +02:00
}
return p_sel;
}
#define SX (getmaxx(stdscr))
#define SY (getmaxy(stdscr))
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
list_selection *do_selection(list_selection * sel, const char *title,
void (*perform) (list_selection *, void *), void *data)
2010-08-08 10:06:34 +02:00
{
2011-03-07 08:02:35 +01:00
WINDOW *wn;
bool update = true;
2010-08-08 10:06:34 +02:00
list_selection *s;
list_selection *top = sel;
list_selection *current = top;
int i;
2011-03-07 08:02:35 +01:00
int height = 0, width = (int)strlen(title) + 8;
for (s = sel; s; s = s->next) {
2012-05-16 07:21:59 +02:00
if ((int)strlen(s->str) > width) {
2011-03-07 08:02:35 +01:00
width = (int)strlen(s->str);
2012-05-16 07:21:59 +02:00
}
2010-08-08 10:06:34 +02:00
++height;
2012-05-16 07:21:59 +02:00
if (verbosity >= 5) {
log_printf(stdout, "s %s w %d h %d\n", s->str, width, height);
}
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (height == 0 || width == 0)
2012-05-16 07:21:59 +02:00
return 0;
2011-03-07 08:02:35 +01:00
if (width + 3 > SX)
width = SX - 4;
if (height + 2 > SY)
height = SY - 2;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
if (verbosity >= 5)
2012-05-16 07:21:59 +02:00
log_printf(stdout, "w %d h %d\n", width, height);
2011-03-07 08:02:35 +01:00
wn =
newwin(height + 2, width + 4, (SY - height - 2) / 2, (SX - width - 4) / 2);
2010-08-08 10:06:34 +02:00
for (;;) {
int input;
if (update) {
2011-03-07 08:02:35 +01:00
for (s = top; s != NULL && top->index + height != s->index; s = s->next) {
i = s->index - top->index;
2010-08-08 10:06:34 +02:00
wmove(wn, i + 1, 4);
waddnstr(wn, s->str, -1);
wclrtoeol(wn);
}
wclrtobot(wn);
2010-09-12 05:11:15 +02:00
wxborder(wn);
2010-08-08 10:06:34 +02:00
mvwprintw(wn, 0, 2, "[ %s ]", title);
update = false;
}
2011-03-07 08:02:35 +01:00
i = current->index - top->index;
2010-08-08 10:06:34 +02:00
wattron(wn, A_BOLD | COLOR_PAIR(COLOR_YELLOW));
wmove(wn, i + 1, 2);
waddstr(wn, "->");
wmove(wn, i + 1, 4);
2011-03-07 08:02:35 +01:00
waddnstr(wn, current->str, width - 2);
2010-08-08 10:06:34 +02:00
wattroff(wn, A_BOLD | COLOR_PAIR(COLOR_YELLOW));
wrefresh(wn);
input = getch();
wmove(wn, i + 1, 2);
waddstr(wn, " ");
wmove(wn, i + 1, 4);
waddnstr(wn, current->str, width);
switch (input) {
2011-03-07 08:02:35 +01:00
case KEY_NPAGE:
for (i = 0; i != height / 2; ++i) {
if (current->next) {
current = current->next;
if (current->index - height >= top->index) {
top = current;
update = true;
}
}
}
break;
case KEY_PPAGE:
for (i = 0; i != height / 2; ++i) {
if (current->prev) {
if (current == top) {
top = sel;
while (top->index + height < current->index)
top = top->next;
update = true;
}
current = current->prev;
}
}
break;
case KEY_DOWN:
2010-08-08 10:06:34 +02:00
if (current->next) {
current = current->next;
2011-03-07 08:02:35 +01:00
if (current->index - height >= top->index) {
top = current;
2010-08-08 10:06:34 +02:00
update = true;
}
}
2011-03-07 08:02:35 +01:00
break;
case KEY_UP:
2010-08-08 10:06:34 +02:00
if (current->prev) {
2011-03-07 08:02:35 +01:00
if (current == top) {
2010-08-08 10:06:34 +02:00
top = sel;
2011-03-07 08:02:35 +01:00
while (top->index + height < current->index)
top = top->next;
2010-08-08 10:06:34 +02:00
update = true;
}
current = current->prev;
}
2011-03-07 08:02:35 +01:00
break;
case 27:
case 'q':
delwin(wn);
return NULL;
case 10:
case 13:
if (perform)
perform(current, data);
else {
delwin(wn);
return current;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
break;
default:
s = current->next;
if (s == NULL)
s = top;
while (s != current) {
if (tolower(s->str[0]) == tolower(input)) {
current = s;
update = true;
} else {
s = s->next;
if (s == NULL)
s = top;
}
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
if (current->index - height >= top->index) {
top = current;
2010-08-08 10:06:34 +02:00
update = true;
}
}
}
}