#line 20 "save.c-nw"
#include <config.h>
#include <Xm/Xm.h>
#include <Xm/FileSB.h>
#include <w3a.h>
#include <str.h>

#define MAXNAMELEN 1024

typedef struct {
    char *filename;
    FILE *f;
    Bool done;
} *SaveInfo;

typedef struct _Assoc {
    long id;
    SaveInfo b;
    struct _Assoc *next;
} *Assoc;

static Assoc assoclist = NULL;

/* store -- store an ID/Buffer combination */
static void store(SaveInfo b, long id)
{
    Assoc h;
    new(h); h->id = id; h->b = b; h->next = assoclist; assoclist = h;
}

/* delete -- delete an ID/Buffer combination */
static void delete(long id)
{
    Assoc g, h;
    assert(assoclist);
    if (assoclist->id == id) {
        h = assoclist; assoclist = assoclist->next; dispose(h);
    } else {
        assert(h->next);
        for (h = assoclist; h->next->id != id; h = h->next) assert(h->next);
        g = h->next; h->next = g->next; dispose(g);
    }
}

/* find -- find the Buffer associated with an ID */
static SaveInfo find(long id)
{
    Assoc h;
    assert(assoclist);
    for (h = assoclist; h->id != id; h = h->next) assert(h->next);
    return h->b;
}

static Widget dialog = NULL;


EXPORT Bool initSave(char ***mime_types, int *nrtypes, float **prefs)
{
    static char *types[] = {"*/*"};
    static float pref[] = {0.1};

    *mime_types = types;
    *nrtypes = 1;
    *prefs = pref;
    dialog = XmCreateFileSelectionDialog(W3Atoplevel(), "save", NULL, 0);
    return dialog != NULL;
}


static void cb(Widget w, XtPointer client_data, XtPointer call_data)
{
    SaveInfo s = (SaveInfo) client_data;
    XmFileSelectionBoxCallbackStruct *info =
        (XmFileSelectionBoxCallbackStruct *) call_data;

    if (info->reason == XmCR_OK) {
        if (XmStringGetLtoR(info->value, XmFONTLIST_DEFAULT_TAG,
                            &s->filename)) {
            s->f = fopen(s->filename, "w");
        }
    } else {
        assert(info->reason == XmCR_CANCEL);
    }
    s->done = TRUE;
}
#line 115 "save.c-nw"
EXPORT Bool openSave(const W3ADocumentInfo info, W3AWindow window, long id)
{
    SaveInfo s;
    char filename[MAXNAMELEN];
    XtAppContext app_context;

    new(s);
    store(s, id);
    s->done = FALSE;
    s->f = NULL;
    s->filename = NULL;
    app_context = XtWidgetToApplicationContext(window);
    XtAddCallback(dialog, XmNokCallback, cb, s);
    XtAddCallback(dialog, XmNcancelCallback, cb, s);
    /*
     * TO DO: suggest file name
     */
    XtManageChild(dialog);
    while (!s->done)
        /* Don't allow file/socket input while waiting for the dialog */
        XtAppProcessEvent(app_context, XtIMXEvent);

    XtUnmanageChild(dialog);
    XtRemoveCallback(dialog, XmNokCallback, cb, s);
    XtRemoveCallback(dialog, XmNokCallback, cb, s);
    if (s->f != NULL)
        return TRUE;
    else {
        dispose(s);
        return FALSE;
    }
}


EXPORT int writeSave(long id, const char *buf, size_t nchars)
{
    SaveInfo s = find(id);
    return fwrite(buf, 1, nchars, s->f);
}


EXPORT Bool closeSave(long id)
{
    SaveInfo s = find(id);
    FILE *f = s->f;

    dispose(s->filename);
    dispose(s);
    return fclose(f) != -1;
}


EXPORT void eventSave(long id, long sourceid, long eventtype, void *params)
{
    /* Skip */
}


EXPORT Bool infoSave(long id, W3ADocumentInfo *info)
{
    /* TO DO: return file name as title */
    return TRUE;
}