@	The browser maintains a list of requests that are currently
	being executed. New items are added by |W3Aprocess| and
	|W3Asubprocess|. Items are removed when |get_input_cb| has
	finished or when the user presses the interrupt button.

	A pointer to the |ViewerInfo| struct serves as ID for viewers.

	Items aren't really removed, just marked for re-use. The
	interface consists of the functions |get_request_rec|,
	|free_request_rec| and |interrupt_all_request_rec|. The latter
	is called by |interrupt_cb|, when the user presses the
	interrupt button.

<<*>>=
#include "config.h"
#include <Xm/Xm.h>
#include "str.h"
#include "w3a.h"
#include "w3alib.h"


EXPORT typedef struct {
    W3ADocumentInfo *doc;
    int method;					/* GET, POST, etc. */
    int viewer;					/* Which class of viewers */
    int agent;					/* Which class of agents */
    int fd;					/* File descriptor for agent */
    int total;					/* # of bytes read */
    Widget w;					/* Widget created by browser */
    int seqnr;					/* Unique number */
    int cache_id;				/* -1 if not caching */
    XtInputId write_id, read_id;		/* Input handlers */
    Bool interrupted;				/* Flag to stop input hndlr */
    Bool need_event;				/* Call W3Aevent when ready? */
    Bool toplevel;				/* Document or in-line? */
    int show_progress;				/* Which percentagebar */
    int tmpfd;					/* Temp. file, for "save" */
    char tmpnam[L_tmpnam];			/* Temp file */
    Bool in_use;				/* Used by requests.c only */
    Bool high_prio;				/* Priority request */
    int private;				/* Used by requests.c only */
} ViewerInfo;

static ViewerInfo **list = NULL;
static int listlen = 0;


EXPORT ViewerInfo * get_request_rec(void)
{
    int i;

    for (i = 0; i < listlen && list[i]->in_use; i++) ;
    if (i == listlen) {
	listlen++;
	renewarray(list, listlen);
	new(list[i]);
	list[i]->private = i;
    }
    list[i]->doc = NULL;
    list[i]->method = -1;
    list[i]->viewer = -1;
    list[i]->agent = -1;
    list[i]->fd = -1;
    list[i]->total = 0;
    list[i]->w = NULL;
    list[i]->seqnr = -1;
    list[i]->cache_id = -1;
    list[i]->write_id = NULL;
    list[i]->read_id = NULL;
    list[i]->interrupted = FALSE;
    list[i]->need_event = FALSE;
    list[i]->toplevel = FALSE;
    list[i]->show_progress = -1;
    list[i]->tmpfd = -1;
    list[i]->tmpnam[0] = '\0';
    list[i]->high_prio = FALSE;
    list[i]->in_use = TRUE;
    return list[i];
}


EXPORT Bool free_request_rec(ViewerInfo *v)
{
    Bool ok = TRUE;

    assert(0 <= v->private
	   && v->private < listlen
	   && list[v->private] == v);
    if (! v->in_use) return TRUE;
    if (v->write_id) XtRemoveInput(v->write_id);
    if (v->read_id) XtRemoveInput(v->read_id);
    if (v->agent >= 0 && v->fd >= 0) ok &= agent_close(v->agent, v->fd);
    if (v->viewer >= 0) ok &= viewer_close(v->viewer, (long) v);
#if 0
    if (v->w) XtDestroyWidget(v->w);
#endif
    if (v->doc) {dispose_doc(v->doc); v->doc = NULL;}
    if (v->tmpfd >= 0) (void) close(v->tmpfd);
    if (v->tmpnam[0]) (void) unlink(v->tmpnam);
    v->in_use = FALSE;
    return ok;
}


EXPORT void interrupt_all_request_rec(void)
{
    int i;

    for (i = 0; i < listlen; i++) list[i]->interrupted = TRUE;
}


EXPORT ViewerInfo *get_first_request_rec()
{
    int i;

    for (i = 0; i < listlen; i++)
	if (list[i]->in_use) return list[i];
    return NULL;
}


EXPORT ViewerInfo *get_next_request_rec(ViewerInfo *prev)
{
    int i;

    assert(0 <= prev->private
	   && prev->private < listlen
	   && list[prev->private] == prev);
    for (i = prev->private + 1; i < listlen; i++)
	if (list[i]->in_use) return list[i];
    return NULL;
}
