summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.in8
-rw-r--r--src/help.c4
-rw-r--r--src/list_display.c363
-rw-r--r--src/list_generic.c266
-rw-r--r--src/list_generic.h63
5 files changed, 492 insertions, 212 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 8120726..0706290 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -62,11 +62,12 @@ CFILES= screen.c ansi.c fileio.c mark.c misc.c resize.c socket.c \
termcap.c input.c attacher.c pty.c process.c display.c comm.c \
kmapdef.c acls.c braille.c braille_tsi.c logfile.c layer.c \
sched.c teln.c nethack.c encoding.c canvas.c layout.c viewport.c \
- list_display.c
+ list_display.c list_generic.c
OFILES= screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \
search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \
termcap.o input.o attacher.o pty.o process.o display.o comm.o \
kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \
+ list_generic.o list_display.o \
sched.o teln.o nethack.o encoding.o canvas.o layout.o viewport.o
all: screen
@@ -303,7 +304,7 @@ loadav.o: layout.h viewport.h canvas.h loadav.c config.h screen.h os.h osdef.h a
comm.h layer.h term.h image.h display.h window.h extern.h
putenv.o: layout.h viewport.h canvas.h putenv.c config.h
help.o: layout.h viewport.h canvas.h help.c config.h screen.h os.h osdef.h ansi.h acls.h \
- comm.h layer.h term.h image.h display.h window.h extern.h list_display.c
+ comm.h layer.h term.h image.h display.h window.h extern.h list_display.c list_generic.h
termcap.o: layout.h viewport.h canvas.h termcap.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h
input.o: layout.h viewport.h canvas.h input.c config.h screen.h os.h osdef.h ansi.h acls.h \
@@ -346,3 +347,6 @@ layout.o: layout.h viewport.h canvas.h layout.c config.h screen.h os.h osdef.h a
viewport.o: layout.h viewport.h canvas.h viewport.c config.h screen.h os.h osdef.h ansi.h acls.h \
comm.h layer.h term.h image.h display.h window.h extern.h \
braille.h
+list_generic.o: list_generic.h list_generic.c layer.h
+list_display.o: list_generic.h list_display.c layer.h
+
diff --git a/src/help.c b/src/help.c
index e98f50c..1e37354 100644
--- a/src/help.c
+++ b/src/help.c
@@ -33,6 +33,8 @@
#include "screen.h"
#include "extern.h"
+#include "list_generic.h"
+
char version[60]; /* initialised by main() */
extern struct layer *flayer;
@@ -681,8 +683,6 @@ int y, xs, xe, isblank;
}
-#include "list_display.c"
-
/*
**
** here is the windowlist
diff --git a/src/list_display.c b/src/list_display.c
index 3693f01..28ec7bb 100644
--- a/src/list_display.c
+++ b/src/list_display.c
@@ -1,4 +1,7 @@
-/* Copyright (c) 2008, 2009
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ * Copyright (c) 2008, 2009
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Micah Cowan (micah@cowan.name)
@@ -28,150 +31,16 @@
/* Deals with the list of displays */
-#ifdef MULTI
-
-struct displaysdata
-{
- struct display *selected; /* The selected display */
- struct display *current; /* The current display (that's showing this list) */
-};
-
-static void DisplaysProcess __P((char **, int *));
-static void DisplaysRedisplayLine __P((int, int, int, int));
-static void displayspage __P((struct displaysdata *));
-
-static struct LayFuncs DisplaysLf =
-{
- DisplaysProcess,
- HelpAbort,
- DisplaysRedisplayLine,
- DefClearLine,
- DefRewrite,
- DefResize,
- DefRestore
-};
+#include "config.h"
-void
-display_displays()
-{
- struct displaysdata *ddata;
- if (flayer->l_width < 10 || flayer->l_height < 5)
- {
- LMsg(0, "Window size too small for displays page");
- return;
- }
- if (InitOverlayPage(sizeof(struct displaysdata), &DisplaysLf, 0))
- return;
- flayer->l_mode = 1;
- flayer->l_x = 0;
- flayer->l_y = flayer->l_height - 1;
- ddata = flayer->l_data;
- ddata->current = display;
- ddata->selected = display;
- displayspage(ddata);
-}
+#include "screen.h"
+#include "list_generic.h"
-static void
-display_list_change(struct displaysdata *ddata, int dir)
-{
- struct display *d;
- for (d = displays; d; d = d->d_next)
- {
- if (dir == -1 && d->d_next == ddata->selected)
- {
- ddata->selected = d;
- break;
- }
- else if (dir == 1 && d == ddata->selected && d->d_next)
- {
- ddata->selected = d->d_next;
- break;
- }
- }
-
- if (d)
- {
- /* Selection changed */
- displayspage(ddata);
- }
-}
-
-static void
-DisplaysProcess(ppbuf, plen)
-char **ppbuf;
-int *plen;
-{
- int done = 0;
-
- ASSERT(flayer);
- while (!done && *plen > 0)
- {
- unsigned char ch = (unsigned char)**ppbuf;
- ++*ppbuf;
- --*plen;
- if (flayer->l_mouseevent.start)
- {
- int r = LayProcessMouse(flayer, ch);
- if (r == -1)
- LayProcessMouseSwitch(flayer, 0);
- else
- {
- if (r)
- ch = 0222;
- else
- continue;
- }
- }
- switch (ch)
- {
- case ' ':
- displayspage(flayer->l_data);
- break;
- case '\r':
- case '\n':
- HelpAbort();
- done = 1;
- break;
-
- case 0220: /* up */
- case 16: /* ^P like emacs */
- case 'k':
- display_list_change(flayer->l_data, -1);
- break;
-
- case 0216: /* down */
- case 14: /* ^N like emacs */
- case 'j':
- display_list_change(flayer->l_data, 1);
- break;
-
- case 0222: /* mouse event */
- if (flayer->l_mouseevent.start)
- {
- /* All the data is available to process the mouse event. */
- int button = flayer->l_mouseevent.buffer[0];
- if (button == 'a')
- {
- /* Scroll down */
- display_list_change(flayer->l_data, 1);
- }
- else if (button == '`')
- {
- /* Scroll up */
- display_list_change(flayer->l_data, -1);
- }
- LayProcessMouseSwitch(flayer, 0);
- }
- else
- LayProcessMouseSwitch(flayer, 1);
- break;
-
- default:
- break;
- }
- }
-}
+#ifdef MULTI
+extern struct layer *flayer;
+extern struct display *display, *displays;
+extern struct mchar mchar_blank, mchar_so;
/*
* layout of the displays page is as follows:
@@ -180,7 +49,7 @@ xterm 80x42 jnweiger@/dev/ttyp4 0(m11) &rWx
facit 80x24 nb mlschroe@/dev/ttyhf 11(tcsh) rwx
xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
- | | | | | | | | ¦___ window permissions
+ | | | | | | | | ¦___ window permissions
| | | | | | | | (R. is locked r-only,
| | | | | | | | W has wlock)
| | | | | | | |___ Window is shared
@@ -191,97 +60,175 @@ xterm 80x42 jnhollma@/dev/ttyp5 0(m11) &R.x
| | |___ Display is in nonblocking mode. Shows 'NB' if obuf is full.
| |___ Displays geometry as width x height.
|___ the terminal type known by screen for this display.
-
+
*/
-static void
-displayspage(ddata)
-struct displaysdata *ddata;
+static int
+gl_Display_header(struct ListData *ldata)
{
- int y, l;
+ leftline("term-type size user interface window Perms", 0, 0);
+ leftline("---------- ------- ---------- ----------------- ---------- -----", 1, 0);
+ return 2;
+}
+
+static int
+gl_Display_footer(struct ListData *ldata)
+{
+ centerline("[Press Space to refresh; Return to end.]", flayer->l_height - 1);
+}
+
+static int
+gl_Display_row(struct ListData *ldata, struct ListRow *lrow)
+{
+ struct display *d = lrow->data;
char tbuf[80];
- struct display *d;
- struct win *w;
static char *blockstates[5] = {"nb", "NB", "Z<", "Z>", "BL"};
+ struct win *w = d->d_fore;
struct mchar m_current = mchar_blank;
m_current.attr = A_BD;
- if (!ddata)
- return;
+ sprintf(tbuf, " %-10.10s%4dx%-4d%10.10s@%-16.16s%s",
+ d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
+ d->d_usertty,
+ (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
- LClearAll(flayer, 0);
+ if (w)
+ {
+ int l = 10 - strlen(w->w_title);
+ if (l < 0)
+ l = 0;
+ sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
+ w->w_number, w->w_title, l, "",
+ /* w->w_dlist->next */ 0 ? '&' : ' ',
+ /*
+ * The rwx triple:
+ * -,r,R no read, read, read only due to foreign wlock
+ * -,.,w,W no write, write suppressed by foreign wlock,
+ * write, own wlock
+ * -,x no execute, execute
+ */
+#ifdef MULTIUSER
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
+ ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
+ 'r' : 'R')),
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
+ ((w->w_wlock == WLOCK_OFF) ? 'w' :
+ ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
+ (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
+#else
+ 'r', 'w', 'x'
+#endif
+ );
+ }
+ leftline(tbuf, lrow->y, lrow == ldata->selected ? &mchar_so : d == display ? &m_current : 0);
- leftline("term-type size user interface window Perms", 0, 0);
- leftline("---------- ------- ---------- ----------------- ---------- -----", 1, 0);
- y = 2;
+ return 1;
+}
+static void
+gl_Display_rebuild(struct ListData *ldata)
+{
+ /* recreate the rows */
+ struct display *d;
+ struct ListRow *row = NULL;
for (d = displays; d; d = d->d_next)
{
- struct mchar *mc;
- w = d->d_fore;
+ row = glist_add_row(ldata, d, row);
+ if (d == display)
+ ldata->selected = row;
+ }
- if (y >= flayer->l_height - 3)
- break;
- sprintf(tbuf, " %-10.10s%4dx%-4d%10.10s@%-16.16s%s",
- d->d_termname, d->d_width, d->d_height, d->d_user->u_name,
- d->d_usertty,
- (d->d_blocked || d->d_nonblock >= 0) && d->d_blocked <= 4 ? blockstates[d->d_blocked] : " ");
+ glist_display_all(ldata);
+}
- if (w)
- {
- l = 10 - strlen(w->w_title);
- if (l < 0)
- l = 0;
- sprintf(tbuf + strlen(tbuf), "%3d(%.10s)%*s%c%c%c%c",
- w->w_number, w->w_title, l, "",
- /* w->w_dlist->next */ 0 ? '&' : ' ',
- /*
- * The rwx triple:
- * -,r,R no read, read, read only due to foreign wlock
- * -,.,w,W no write, write suppressed by foreign wlock,
- * write, own wlock
- * -,x no execute, execute
- */
-#ifdef MULTIUSER
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
- ((w->w_wlock == WLOCK_OFF || d->d_user == w->w_wlockuser) ?
- 'r' : 'R')),
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' :
- ((w->w_wlock == WLOCK_OFF) ? 'w' :
- ((d->d_user == w->w_wlockuser) ? 'W' : 'v'))),
- (AclCheckPermWin(d->d_user, ACL_READ, w) ? '-' : 'x')
+static int
+gl_Display_input(struct ListData *ldata, char **inp, int *len)
+{
+ struct display *cd = display;
+ unsigned char ch = (unsigned char) **inp;
+
+ ++*inp;
+ --*len;
+
+ switch (ch)
+ {
+ case ' ': /* Space to refresh */
+ glist_remove_rows(ldata);
+ gl_Display_rebuild(ldata);
+ break;
+
+ case '\r':
+ case '\n':
+ glist_abort();
+ *len = 0;
+ break;
+
+ case 'd': /* Detach */
+ case 'D': /* Power detach */
+ display = ldata->selected->data;
+ if (display == cd) /* We do not allow detaching the current display */
+ break;
+ Detach(
+#ifdef POW_DETACH
+ ch == 'D' ? D_REMOTE_POWER : D_REMOTE
#else
- 'r', 'w', 'x'
+ D_REMOTE
#endif
);
- }
- leftline(tbuf, y, d == ddata->selected ? &mchar_so : d == ddata->current ? &m_current : 0);
- if (d == ddata->selected)
- flayer->l_y = y;
- y++;
+ display = cd;
+ glist_remove_rows(ldata);
+ gl_Display_rebuild(ldata);
+ break;
+
+ break;
+
+ default:
+ /* We didn't actually process the input. */
+ --*inp;
+ ++*len;
+ return 0;
}
- sprintf(tbuf,"[Press Space %s Return to end.]",
- 1 ? "to refresh;" : "or");
- centerline(tbuf, flayer->l_height - 2);
- LaySetCursor();
+ return 1;
}
-static void
-DisplaysRedisplayLine(y, xs, xe, isblank)
-int y, xs, xe, isblank;
+static int
+gl_Display_freerow(struct ListData *ldata, struct ListRow *row)
{
- ASSERT(flayer);
- if (y < 0)
+ /* There was no allocation when row->data was set. So nothing to do here. */
+}
+
+static struct GenericList gl_Display =
+{
+ gl_Display_header,
+ gl_Display_footer,
+ gl_Display_row,
+ gl_Display_input,
+ gl_Display_freerow
+};
+
+void
+display_displays()
+{
+ struct display *d;
+ struct ListRow *row = NULL;
+ struct ListData *ldata;
+ if (flayer->l_width < 10 || flayer->l_height < 5)
{
- displayspage(flayer->l_data);
+ LMsg(0, "Window size too small for displays page");
return;
}
- if (y != 0 && y != flayer->l_height - 1)
- return;
- if (isblank)
+
+ ldata = glist_display(&gl_Display);
+ if (!ldata)
return;
- LClearArea(flayer, xs, y, xe, y, 0, 0);
- /* To be filled in... */
+
+ for (d = displays; d; d = d->d_next)
+ {
+ row = glist_add_row(ldata, d, row);
+ if (d == display)
+ ldata->selected = row;
+ }
+ glist_display_all(ldata);
}
#endif /* MULTI */
diff --git a/src/list_generic.c b/src/list_generic.c
new file mode 100644
index 0000000..112b588
--- /dev/null
+++ b/src/list_generic.c
@@ -0,0 +1,266 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#include "screen.h"
+#include "list_generic.h"
+#include "layer.h"
+
+/* Deals with a generic list display */
+
+extern struct layer *flayer;
+
+static void ListProcess __P((char **, int *));
+static void ListAbort __P((void));
+static void ListRedisplayLine __P((int, int, int, int));
+static void ListClearLine __P((int, int, int, int));
+static int ListRewrite __P((int, int, int, struct mchar *, int));
+static int ListResize __P((int, int));
+static void ListRestore __P((void));
+
+static struct LayFuncs ListLf =
+{
+ ListProcess,
+ ListAbort,
+ ListRedisplayLine,
+ ListClearLine,
+ ListRewrite,
+ ListResize,
+ ListRestore
+};
+
+/** Returns non-zero on success. */
+struct ListData *
+glist_display(struct GenericList *list)
+{
+ struct ListData *ldata;
+
+ if (InitOverlayPage(sizeof(struct ListData), &ListLf, 0))
+ return NULL;
+ ldata = flayer->l_data;
+
+ ldata->list_fn = list;
+
+ flayer->l_mode = 1;
+ flayer->l_x = 0;
+ flayer->l_y = flayer->l_height - 1;
+
+ return ldata;
+}
+
+static void ListProcess(char **ppbuf, int *plen)
+{
+ struct ListData *ldata = flayer->l_data;
+
+ while (*plen > 0)
+ {
+ struct ListRow *old;
+ unsigned char ch;
+
+ if (ldata->list_fn->gl_pinput &&
+ ldata->list_fn->gl_pinput(ldata, ppbuf, plen))
+ continue;
+
+ if (!ldata->selected)
+ *plen = 0;
+
+ ch = **ppbuf;
+ ++*ppbuf;
+ --*plen;
+
+ old = ldata->selected;
+ switch (ch)
+ {
+ case ' ':
+ break;
+
+ case '\r':
+ case '\n':
+ break;
+
+ case 0220: /* up */
+ case 16: /* ^P */
+ case 'k':
+ if (!ldata->selected->prev) /* There's no where to go */
+ break;
+ ldata->selected = old->prev;
+ break;
+
+ case 0216: /* down */
+ case 14: /* ^N like emacs */
+ case 'j':
+ if (!ldata->selected->next) /* Nothing to do */
+ break;
+ old = ldata->selected;
+ ldata->selected = old->next;
+ break;
+
+ case 007:
+ ListAbort();
+ *plen = 0;
+ return;
+ }
+
+ if (old == ldata->selected) /* The selection didn't change */
+ continue;
+
+ if (ldata->selected->y == -1)
+ {
+ /* We need to list all the rows, since we are scrolling down */
+ glist_display_all(ldata);
+ }
+ else
+ {
+ /* just redisplay the two lines. */
+ ldata->list_fn->gl_printrow(ldata, old);
+ ldata->list_fn->gl_printrow(ldata, ldata->selected);
+ }
+ }
+}
+
+static void ListAbort(void)
+{
+ struct ListData *ldata = flayer->l_data;
+ glist_remove_rows(ldata);
+ LAY_CALL_UP(LRefreshAll(flayer, 0));
+ ExitOverlayPage();
+}
+
+static void ListRedisplayLine(int y, int xs, int xe, int isblank)
+{
+ ASSERT(flayer);
+ if (y < 0)
+ {
+ glist_display_all(flayer->l_data);
+ return;
+ }
+ if (y != 0 && y != flayer->l_height - 1)
+ return;
+
+ if (isblank)
+ return;
+ LClearArea(flayer, xs, y, xe, y, 0, 0);
+}
+
+static void ListClearLine(int y, int xs, int xe, int bce)
+{
+ DefClearLine(y, xs, xe, bce);
+}
+
+static int ListRewrite(int y, int xs, int xe, struct mchar *rend, int doit)
+{
+ return EXPENSIVE;
+}
+
+static int ListResize (int wi, int he)
+{
+ if (wi < 10 || he < 5)
+ return -1;
+
+ flayer->l_width = wi;
+ flayer->l_height = he;
+ flayer->l_y = he - 1;
+
+ return 0;
+}
+
+static void ListRestore (void)
+{
+ DefRestore();
+}
+
+struct ListRow *
+glist_add_row(struct ListData *ldata, void *data, struct ListRow *after)
+{
+ struct ListRow *r = calloc(1, sizeof(struct ListRow));
+ r->data = data;
+
+ if (after)
+ {
+ r->next = after->next;
+ r->prev = after;
+ after->next = r;
+ if (r->next)
+ r->next->prev = r;
+ }
+ else
+ {
+ r->next = ldata->root;
+ if (ldata->root)
+ ldata->root->prev = r;
+ ldata->root = r;
+ }
+
+ return r;
+}
+
+void
+glist_remove_rows(struct ListData *ldata)
+{
+ struct ListRow *row;
+ for (row = ldata->root; row; row = row->next)
+ {
+ ldata->list_fn->gl_freerow(ldata, row);
+ free(row);
+ }
+ ldata->root = ldata->selected = ldata->top = NULL;
+}
+
+void
+glist_display_all(struct ListData *list)
+{
+ int y;
+ struct ListRow *row;
+
+ LClearAll(flayer, 0);
+
+ y = list->list_fn->gl_printheader(list);
+
+ if (!list->top)
+ list->top = list->root;
+
+ for (row = list->root; row != list->top; row = row->next)
+ row->y = -1;
+
+ for (row = list->top; row; row = row->next)
+ {
+ row->y = y++;
+ if (!list->list_fn->gl_printrow(list, row))
+ {
+ row->y = -1;
+ y--;
+ }
+ if (y + 1 == flayer->l_height)
+ break;
+ }
+ for (; row; row = row->next)
+ row->y = -1;
+
+ list->list_fn->gl_printfooter(list);
+ LaySetCursor();
+}
+
+void glist_abort(void)
+{
+ ListAbort();
+}
+
diff --git a/src/list_generic.h b/src/list_generic.h
new file mode 100644
index 0000000..0c0e5b0
--- /dev/null
+++ b/src/list_generic.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2010
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, see
+ * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ *
+ ****************************************************************
+ */
+
+struct ListData;
+
+struct ListRow
+{
+ void *data; /* Some data relevant to this row */
+ struct ListRow *next, *prev; /* doubly linked list */
+ struct ListRow *parent, *child; /* can also be tree */
+ int y; /* -1 if not on display */
+};
+
+struct GenericList
+{
+ int (*gl_printheader) __P((struct ListData *));
+ int (*gl_printfooter) __P((struct ListData *));
+ int (*gl_printrow) __P((struct ListData *, struct ListRow *));
+ int (*gl_pinput) __P((struct ListData *, char **inp, int *len));
+ int (*gl_freerow) __P((struct ListData *, struct ListRow *));
+};
+
+struct ListData
+{
+ struct ListRow *root; /* The first item in the list */
+ struct ListRow *selected; /* The selected row */
+ struct ListRow *top; /* The topmost visible row */
+
+ struct GenericList *list_fn; /* The functions that deal with the list */
+};
+
+
+struct ListRow * glist_add_row __P((struct ListData *ldata, void *data, struct ListRow *after));
+
+void glist_remove_rows __P((struct ListData *ldata));
+
+void glist_display_all __P((struct ListData *list));
+
+struct ListData * glist_display __P((struct GenericList *list));
+
+void glist_abort __P((void));
+
+void display_displays __P((void));
+