        Create the GUI

        The interface consists of a main window with a menu bar, an area
        for icons of user functions, a list of tabs for accessing the
        last few documents, an area where viewers display their
        documents, and a row of buttons along the bottom.

<<*>>=
#ifndef CIRCPERC
#define CIRCPERC 0
#endif

#include "config.h"
#include <Xm/Xm.h>
#include <X11/xpm.h>
#include <Xm/RepType.h>
#include <Xm/MainW.h>
#include <Xm/TextF.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/CascadeB.h>
#include <Xm/CascadeBG.h>
#include <Xm/Scale.h>
#include <Xm/SeparatoG.h>
#include <Xm/Form.h>
#include <Xm/LabelG.h>
#include <Xm/Frame.h>
#include <Xm/DialogS.h>
#include <Xm/FileSB.h>
#if 1
#include <Xm/PanedW.h>
#else
#include <Xfwf/Stack.h>
#endif
#include <Xm/BulletinB.h>
#include <Xfwf/XmTabs.h>
#if CIRCPERC
#include <Xfwf/CircPerc.h>
#else
#include <Xfwf/PcBar.h>
#endif
#include "w3a.h"
#include "str.h"
#include "w3alib.h"
#include "rcfile.e"
#include "globals.e"
#include "commands.e"
#include "requests.e"
#include "tabs.e"

#define APPCON(w) XtWidgetToApplicationContext(w)

static Widget filebox = NULL;			/* For save-file dialog */
static Widget openbox = NULL;			/* For open-URL dialog */
static Widget bar[MAX_ACTIVE];			/* Progress indicators */


/* show_progress_ready -- show that a transfer is ready */
EXPORT void show_progress_ready(ViewerInfo *v)
{
    XtUnmapWidget(bar[v->show_progress]);
}

/* show_progress -- show how many bytes have been transferred */
EXPORT void show_progress(ViewerInfo *v, int n)
{
    char s[100];
    int p;
    unsigned int percent;

    if (n < 0) {				/* Remove status */
#if CIRCPERC
	XfwfCircularPercentageSetPercentage(bar[v->show_progress], 0);
#else
	XfwfPcBarSetPercentage(bar[v->show_progress], 0);
#endif
#if 0
	XtVaSetValues(status, XtVaTypedArg, XmNlabelString, XtRString,
		      "", 1, NULL);
#endif
    } else if (v->doc->size > 0) {		/* Total size is known */
#if 0
	if (v->total == 0) {			/* First time */
	    p = sprintf(s, "%d Kb", (v->doc->size + 1023)/1024);
	    XtVaSetValues(status, XtVaTypedArg, XmNlabelString, XtRString,
			  s, p + 1, NULL);
	}
#endif
	v->total += n;
#if CIRCPERC
	percent = 10000 * v->total/v->doc->size;
	if (percent > 10000) percent = 10000;
	XfwfCircularPercentageSetPercentage(bar[v->show_progress], percent);
#else
	percent = 100 * v->total/v->doc->size;
	if (percent > 100) percent = 100;
	XfwfPcBarSetPercentage(bar[v->show_progress], percent);
#endif
    } else {					/* Total size not known */
	v->total += n;
#if 0
	p = sprintf(s, "%d Kb", (v->total + 1023)/1024);
	XtVaSetValues(status, XtVaTypedArg, XmNlabelString, XtRString,
		      s, p + 1, NULL);
#endif
#if CIRCPERC
	percent = 10000 * (v->total % 5120)/5120;
	XfwfCircularPercentageSetPercentage(bar[v->show_progress], percent);
#else
	percent = 100 * (v->total % 5120)/5120;
	XfwfPcBarSetPercentage(bar[v->show_progress], percent);
#endif
    }
    XtMapWidget(bar[v->show_progress]);
#if 0
#if 1
    XmUpdateDisplay(status);
#else
    if (XtIsRealized(status)) XFlush(XtDisplay(status));
#endif
#endif
}


static void exit_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
#if 0
    int result;
    XtDestroyWidget(toplevel);
    XtDestroyApplicationContext(app_context);
    XSync(XtDisplay(toplevel), FALSE);
    while ((result = wait(NULL)) != -1 || errno != ECHILD) ;
#endif
    exit(0);
}


static void help_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    goto_url(HELP_URL, TRUE);
}


static void home_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    goto_url(appdata.homepage, FALSE);
}


static void reload_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    ViewerInfo *cur = get_cur_doc();		/* From tabs.c */
    W3ADocumentInfo *doc = new_doc();
    int method = cur->method;

    copy_doc(doc, *cur->doc);
    remove_cur_doc();				/* In tabs.c */
    /* cur doesn't point ot anything anymore */
    W3Aprocess(doc, method, NULL, 0);
    dispose_doc(doc);
}


static void cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    ViewerInfo *v = (ViewerInfo *) client_data;
    XmFileSelectionBoxCallbackStruct *info
	= (XmFileSelectionBoxCallbackStruct *) call_data;
    char *filnam;
    FILE *f, *g;
    int c;

    if (info->reason == XmCR_OK) {
	if (! XmStringGetLtoR(info->value, XmFONTLIST_DEFAULT_TAG, &filnam))
	    XtAppError(APPCON(w), "Cannot get filename??!!");
	assert(v->tmpnam[0] != '\0');
	if (! (f = fopen(v->tmpnam, "r"))) {
	    XtAppWarning(APPCON(w), strerror(errno));
	} else if (! (g = fopen(filnam, "w"))) {
	    XtAppWarning(APPCON(w), "Couldn't open target file");
	} else {
	    while ((c = getc(f)) != EOF) putc(c, g);
	    (void) fclose(f);
	    (void) fclose(g);
	}
    }
    XtUnmanageChild(w);
}


static void save_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    ViewerInfo *v;

    if (! filebox)
	filebox = XmCreateFileSelectionDialog(toplevel, "savedialog", NULL, 0);
    v = get_cur_doc();
    if (v->tmpfd >= 0) {
	XtAppWarning(APPCON(w), "Please wait until the document is complete");
	return;
    }
    XtAddCallback(filebox, XmNokCallback, cb, v);
    XtAddCallback(filebox, XmNcancelCallback, cb, v);
    /* Set default name here... */
    XtManageChild(filebox);
}


/* open_ok -- callback attached to the OK button in the "open URL" dialog */
static void open_ok(Widget w, XtPointer client_data, XtPointer call_data)
{
    Widget entry = (Widget) client_data;
    char *s;

    s = XmTextFieldGetString(entry);
    goto_url(s, FALSE);
    XtFree(s);
}


/* open_cb -- callback attached to the Open button in the main window */
static void open_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    Widget label, sep, entry, ok, cancel;

    if (! openbox) {

    	/* Dialog not yet created */
	openbox = XmCreateFormDialog
	    (toplevel, "open-form", NULL, 0);
	XtVaSetValues
	    (openbox,
	     XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL,
	     XmNfractionBase, 4,
	     NULL);

	/* Add a label, a text field and two buttons to the form */
	label = XtVaCreateManagedWidget
	    ("open-label", xmLabelGadgetClass, openbox,
	     XmNtopAttachment,		XmATTACH_FORM,
	     XmNleftAttachment,		XmATTACH_FORM,
	     XmNbottomPosition,		2,
	     NULL);
	entry = XtVaCreateManagedWidget
	    ("open-text", xmTextFieldWidgetClass, openbox,
	     XmNtopAttachment,		XmATTACH_FORM,
	     XmNrightAttachment,	XmATTACH_FORM,
	     XmNleftAttachment,		XmATTACH_WIDGET,
	     XmNleftWidget,		label,
	     XmNbottomPosition,		2,
	     NULL);
	sep = XtVaCreateManagedWidget
	    ("open-sep", xmSeparatorGadgetClass, openbox,
	     XmNleftAttachment,		XmATTACH_FORM,
	     XmNrightAttachment,	XmATTACH_FORM,
	     XmNtopAttachment,		XmATTACH_WIDGET,
	     XmNtopWidget,		entry,
	     NULL);
	ok = XtVaCreateManagedWidget
	    ("open-ok", xmPushButtonGadgetClass, openbox,
	     XmNtopAttachment,		XmATTACH_WIDGET,
	     XmNtopWidget,		sep,
	     XmNleftAttachment,		XmATTACH_FORM,
	     XmNbottomAttachment,	XmATTACH_FORM,
	     XmNrightPosition,		2,
	     NULL);
	XtAddCallback
	    (ok, XmNactivateCallback, open_ok, entry);
	cancel = XtVaCreateManagedWidget
	    ("open-cancel", xmPushButtonGadgetClass, openbox,
	     XmNtopAttachment,		XmATTACH_WIDGET,
	     XmNtopWidget,		sep,
	     XmNrightAttachment,	XmATTACH_FORM,
	     XmNbottomAttachment,	XmATTACH_FORM,
	     XmNleftPosition,		2,
	     NULL);
	XtVaSetValues
	    (openbox, XmNcancelButton, cancel, XmNdefaultButton, ok, NULL);
    }
    XtManageChild(openbox);
}


/* open2_cb -- callback attached to the Location field in the main window */
static void open2_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    char *s;

    s = XmTextFieldGetString(location);
    goto_url(s, FALSE);
    XtFree(s);
}


static void clone_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    clone_argo();
}


/* source_cb -- callback for a click on the view-source button */
static void source_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    ViewerInfo *v;
    v = get_cur_doc();
    goto_url(v->tmpnam, TRUE);
}


/* interrupt_cb -- callback for a click on the interrupt button */
static void interrupt_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    debug("*** Interrupted!\n");
    interrupt_all_request_rec();
    XtSetSensitive(w, FALSE);
}


/* tabs_cb -- callback for a click on the tabs */
static void tabs_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    ViewerInfo *cur;

    switch_to_tabbed_doc(curopendoc + (int) call_data);
    cur = get_cur_doc();
    if (cur) W3Aevent(0, NEW_DOCUMENT, cur->doc);
    
}


EXPORT void create_windows(void)
{
    Widget filebutton, helpbutton, help, functionsbutton, locationlabel;
    Widget main, menubar, form, filemenu, helpmenu;
    int i;

    main = XtVaCreateManagedWidget
	("main", xmMainWindowWidgetClass, toplevel, NULL);

    /* Children of "main" */
    menubar = XmCreateMenuBar(main, "menubar", NULL, 0);
    form = XtVaCreateManagedWidget("form", xmFormWidgetClass, main, NULL);
    XtManageChild(menubar);
    XmMainWindowSetAreas(main, menubar, NULL, NULL, NULL, form);

    /* Children of "form" */
    tools = XtVaCreateManagedWidget
	("tools", xmRowColumnWidgetClass, form,
	 XmNbottomAttachment, XmATTACH_FORM,
	 XmNleftAttachment, XmATTACH_FORM,
	 XmNtopAttachment, XmATTACH_FORM,
	 NULL);
    locationlabel = XtVaCreateManagedWidget
	("locationlabel", xmLabelGadgetClass, form,
	 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, tools,
	 XmNtopAttachment, XmATTACH_FORM,
	 NULL);
    location = XtVaCreateManagedWidget
	("location", xmTextFieldWidgetClass, form,
	 XmNrightAttachment, XmATTACH_FORM,
	 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, locationlabel,
	 XmNtopAttachment, XmATTACH_FORM,
	 NULL);
    tabs = XtVaCreateManagedWidget
	("tabs", xmTabsWidgetClass, form,
	 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, tools,
	 XmNrightAttachment, XmATTACH_FORM,
	 XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, location,
	 XmNtopOffset, 5,
	 NULL);
    area = XtVaCreateManagedWidget
	("area", xmFormWidgetClass, form,
	 XmNbottomAttachment, XmATTACH_FORM,
	 XmNrightAttachment, XmATTACH_FORM,
	 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, tools,
	 XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, tabs,
	 XmNtopOffset, -1,
	 XmNresizable, FALSE,
	 NULL);

    XtAddCallback(tabs, XtNactivateCallback, tabs_cb, NULL);
    XtAddCallback(location, XtNactivateCallback, open2_cb, NULL);

    /* Children of "tools" (apart from user functions) */
    XtAddCallback(XtVaCreateManagedWidget
		  ("home", xmPushButtonGadgetClass, tools, NULL),
		  XmNactivateCallback, home_cb, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("save", xmPushButtonGadgetClass, tools, NULL),
		  XmNactivateCallback, save_cb, NULL);
#if 0
    XtAddCallback(XtVaCreateManagedWidget
		  ("open", xmPushButtonGadgetClass, tools, NULL),
		  XmNactivateCallback, open_cb, NULL);
#endif
    XtAddCallback(XtVaCreateManagedWidget
		  ("reload", xmPushButtonGadgetClass, tools, NULL),
		  XmNactivateCallback, reload_cb, NULL);
#if 0
    XtAddCallback(XtVaCreateManagedWidget
		  ("clone", xmPushButtonGadgetClass, tools, NULL),
		  XmNactivateCallback, clone_cb, NULL);
#endif
    interrupt = XtVaCreateManagedWidget
	("interrupt", xmPushButtonGadgetClass, tools,
	 XtNsensitive, FALSE, NULL);
    XtAddCallback(interrupt, XmNactivateCallback, interrupt_cb, NULL);

    for (i = 0; i < MAX_BARS_SHOWN; i++)
	bar[i] = XtVaCreateManagedWidget
	    ("bar",
#if CIRCPERC
	     xfwfCircularPercentageWidgetClass,
#else
	     xfwfPcBarWidgetClass,
#endif
	     tools,
	     XmNborderWidth, 0, NULL);
#if 0
    status = XtVaCreateManagedWidget
	("status", xmLabelGadgetClass, tools, NULL);
#endif

    /* Children of "menubar" */
    filebutton = XtVaCreateManagedWidget
	("filebutton", xmCascadeButtonGadgetClass, menubar, NULL);
    functionsbutton = XtVaCreateManagedWidget
	("functionsbutton", xmCascadeButtonGadgetClass, menubar, NULL);
    helpbutton = XtVaCreateManagedWidget
	("helpbutton", xmCascadeButtonGadgetClass, menubar, NULL);

    filemenu = XmCreatePulldownMenu(menubar, "filemenu", NULL, 0);
    functionsmenu = XmCreatePulldownMenu(menubar, "functionsmenu", NULL, 0);
    helpmenu = XmCreatePulldownMenu(menubar, "helpmenu", NULL, 0);

    XtVaSetValues(filebutton, XmNsubMenuId, filemenu, NULL);
    XtVaSetValues(functionsbutton, XmNsubMenuId, functionsmenu, NULL);
    XtVaSetValues(helpbutton, XmNsubMenuId, helpmenu, NULL);
    XtVaSetValues(menubar, XmNmenuHelpWidget, helpbutton, NULL);

    /* Children of "filemenu" */
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-open", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, open_cb, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-save", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, save_cb, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-home", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, home_cb, NULL);
    (void) XtVaCreateManagedWidget
	("menu-sep", xmSeparatorGadgetClass, filemenu, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-reload", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, reload_cb, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-source", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, source_cb, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-clone", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, clone_cb, NULL);
    (void) XtVaCreateManagedWidget
	("menu-sep", xmSeparatorGadgetClass, filemenu, NULL);
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-exit", xmPushButtonGadgetClass, filemenu, NULL),
		  XmNactivateCallback, exit_cb, NULL);

    /* Children of "helpmenu" */
    XtAddCallback(XtVaCreateManagedWidget
		  ("menu-help", xmPushButtonGadgetClass, helpmenu, NULL),
		  XmNactivateCallback, help_cb, NULL);

    /* Create widgets for the tabs */
    init_tabs();				/* In tabs.c */

    /* Map the windows */
    XtRealizeWidget(toplevel);
}
