#line 16 "html.c-nw"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define USE_STATUS 1
#define USE_BALLOON 0
#line 40 "html.c-nw"
typedef struct _IdWidget {
long id;
Widget w;
struct _IdWidget *next;
} *IdWidget;
typedef struct {
W3ADocumentInfo *info;
Widget w; /* HTML widget */
#if USE_STATUS
Widget status; /* Label with URL */
#endif
#ifdef USE_BALLOON
Widget balloon;
#endif
long nchars; /* Needed in infoHTML */
IdWidget idlist;
} *Instance;
typedef struct _IdInstance {
long id;
Instance i;
struct _IdInstance *next;
} *IdInstance;
static IdInstance instancelist = NULL;
static void store_id(Instance instance, long id, Widget w)
{
IdWidget h;
new(h); h->id = id; h->w = w; h->next = instance->idlist;
instance->idlist = h;
}
static Widget id_to_widget(Instance instance, long id)
{
IdWidget p;
for (p = instance->idlist; p; p = p->next)
if (p->id == id) return p->w;
return NULL;
}
static void dispose_idlist(IdWidget list)
{
if (list) {
if (list->id != -1) W3AcloseView(list->id);
dispose_idlist(list->next);
dispose(list);
}
}
/* store -- store an ID/Instance combination */
static void store(Instance i, long id)
{
IdInstance h;
new(h); h->id = id; h->i = i; h->next = instancelist; instancelist = h;
}
/* delete -- delete an ID/Instance combination */
static void delete(long id)
{
IdInstance g, h;
assert(instancelist);
if (instancelist->id == id) {
h = instancelist; instancelist = instancelist->next; dispose(h);
} else {
assert(instancelist->next);
for (h = instancelist; h->next->id != id; h = h->next) assert(h->next);
g = h->next; h->next = g->next; dispose(g);
}
}
/* find -- find the Instance associated with an ID */
static Instance find(long id)
{
IdInstance h;
assert(instancelist);
for (h = instancelist; h->id != id; h = h->next) assert(h->next);
return h->i;
}
#line 128 "html.c-nw"
static void activate_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
XfwfFTextCallbackStruct *info = (XfwfFTextCallbackStruct *) call_data;
XfwfSSGMLData *data = (XfwfSSGMLData *) info->data;
char *url = data->url;
Instance instance = (Instance) client_data;
W3ADocumentInfo *doc;
/* debug("html activate: %s\n", data->url); */
#if USE_BALLOON
if (instance->balloon) {
XtPopdown(instance->balloon);
instance->balloon = NULL;
}
#endif
doc = new_doc();
if (data->ismap) { /* Append x,y */
newarray(doc->url, strlen(url) + 25);
sprintf(doc->url, "%s?%d,%d", url, info->x, info->y);
} else
doc->url = newstring(url);
doc->referer = newstring(instance->info->url);
(void) W3Aprocess(doc, GET_METHOD, NULL, 0);
dispose_doc(doc);
}
#line 161 "html.c-nw"
static void activate_form_cb(Widget w, XtPointer client_data,
XtPointer call_data)
{
XfwfActivateFormInfo *info = (XfwfActivateFormInfo *) call_data;
Instance instance = (Instance) client_data;
W3ADocumentInfo *doc;
/* debug("html activate_form: %s\n", info->url); */
#if USE_BALLOON
if (instance->balloon) {
XtPopdown(instance->balloon);
instance->balloon = NULL;
}
#endif
doc = new_doc();
doc->url = newstring(info->url);
doc->referer = newstring(instance->info->url);
(void) W3Aprocess(doc, info->method, info->data, info->length);
dispose_doc(doc);
}
#line 187 "html.c-nw"
static void enterleave_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
#if USE_STATUS || USE_BALLOON
XfwfFTextCallbackStruct *info = (XfwfFTextCallbackStruct *) call_data;
XfwfSSGMLData *data = (XfwfSSGMLData *) info->data;
Instance instance = (Instance) client_data;
URI base, uri;
Position x, y;
char *url;
#endif
#if USE_STATUS
if (info->reason == XfwfEnter) {
if (! URL_parse(data->url, &uri)) return; /* Error in URL */
if (uri.tp == URI_Rel) {
if (! URL_parse(instance->info->url, &base)) return; /* ??? */
URL_expand(&uri, base);
}
url = uri2str(uri);
XtVaSetValues(instance->status, XtVaTypedArg, XmNlabelString,
XtRString, url, strlen(url), NULL);
dispose(url);
} else {
assert(info->reason == XfwfLeave);
XtVaSetValues(instance->status, XtVaTypedArg, XmNlabelString,
XtRString, "", 1, NULL);
}
#endif
#if USE_BALLOON
if (info->reason == XfwfEnter) {
if (! URL_parse(data->url, &uri)) return; /* Error in URL */
if (uri.tp == URI_Rel) {
if (! URL_parse(instance->info->url, &base)) return; /* ??? */
URL_expand(&uri, base);
}
url = uri2str(uri);
XtTranslateCoords(instance->w, info->x, info->y, &x, &y);
instance->balloon = XtVaCreatePopupShell
("balloon", overrideShellWidgetClass, instance->w,
XtNx, x + 5, XtNy, y + 5, NULL);
(void) XtVaCreateManagedWidget
("balloon-label", xmLabelWidgetClass, instance->balloon,
XtVaTypedArg, XmNlabelString, XtRString, url, strlen(url),
NULL);
dispose(url);
XtPopup(instance->balloon, XtGrabNone);
} else {
assert(info->reason == XfwfLeave);
if (instance->balloon) XtDestroyWidget(instance->balloon);
instance->balloon = NULL;
}
#endif
}
#line 250 "html.c-nw"
static void resolve_cb(Widget w, XtPointer client_data, XtPointer call_data)
{
XfwfResolveRec *info = (XfwfResolveRec *) call_data;
Instance instance = (Instance) client_data;
W3ADocumentInfo *doc;
long id;
/* fprintf(stderr, "resolve image: %s\n", info->url); */
doc = new_doc();
doc->url = newstring(info->url);
doc->referer = newstring(instance->info->url);
id = W3Asubprocess(doc, GET_METHOD, NULL, 0, info->widget);
store_id(instance, id, info->widget);
dispose_doc(doc);
}
EXPORT Bool initHTML(char ***mime_types, int *nrtypes, float **prefs)
{
static char *types[] = {"text/html"};
static float pref[] = {1.0};
*mime_types = types;
*nrtypes = 1;
*prefs = pref;
return TRUE;
}
EXPORT Bool openHTML(const W3ADocumentInfo doc, W3AWindow workarea, long id)
{
Widget w, form, status;
Instance instance;
Pixmap bg;
new(instance);
store(instance, id);
#if USE_STATUS
#define STATUS_HT 20
#if 1
form = XtVaCreateManagedWidget
("html-form", xmFormWidgetClass, workarea, NULL);
w = XtVaCreateManagedWidget
("html", xfwfHTML2WidgetClass, form,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
XmNbottomOffset, STATUS_HT,
XtNbase, doc.url,
NULL);
status = XtVaCreateManagedWidget
("html-status", xmLabelWidgetClass, form,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, w,
XmNbottomAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
#else /* 0 */
form = XtVaCreateManagedWidget
("html-form", xmPanedWindowWidgetClass, workarea, NULL);
w = XtVaCreateManagedWidget
("html", xfwfHTML2WidgetClass, form, NULL);
status = XtVaCreateManagedWidget
("html-status", xmLabelWidgetClass, form, NULL);
#endif /* 0 */
#else /* USE_STATUS */
w = XtVaCreateManagedWidget("html", xfwfHTML2WidgetClass, workarea, NULL);
#endif
XtAddCallback(w, XtNactivate, activate_cb, instance);
XtAddCallback(w, XtNactivateForm, activate_form_cb, instance);
XtAddCallback(w, XtNenter, enterleave_cb, instance);
XtAddCallback(w, XtNleave, enterleave_cb, instance);
XtAddCallback(w, XtNresolveURL, resolve_cb, instance);
instance->w = w;
#if USE_STATUS
instance->status = status;
#endif
#if USE_BALLOON
instance->balloon = NULL;
#endif
instance->info = new_doc();
copy_doc(instance->info, doc);
instance->nchars = 0;
instance->idlist = NULL;
#if 0
/* Nice background (this is not the way it should be done, though) */
if (XpmReadFileToPixmap
(XtDisplay(w), RootWindowOfScreen(XtScreen(w)),
"Flock.pm", &bg, NULL, NULL) == XpmSuccess) {
XtVaSetValues(w, XtNbackgroundPixmap, bg, NULL);
XtVaSetValues(XtParent(w), XtNbackgroundPixmap, bg, NULL);
}
#endif
return TRUE;
}
EXPORT Bool infoHTML(long id, W3ADocumentInfo *info)
{
Instance instance = find(id);
char *s = NULL;
XtVaGetValues(instance->w, XtNtitle, &s, NULL);
if (s) {
dispose(info->title);
info->title = newstring(s);
trim(info->title);
dispose(instance->info->title);
instance->info->title = newstring(info->title);
}
info->size = instance->nchars;
return TRUE;
}
EXPORT int writeHTML(long id, const char *buf, size_t nbytes)
{
Instance instance = find(id);
Widget workarea = XtParent(XtParent(instance->w));
XfwfAddText(instance->w, buf, nbytes);
instance->nchars += nbytes;
return nbytes;
}
EXPORT Bool closeHTML(long id)
{
Instance instance = find(id);
#if USE_STATUS
XtDestroyWidget(XtParent(instance->w));
#else
XtDestroyWidget(instance->w);
#endif
dispose_doc(instance->info);
dispose_idlist(instance->idlist);
delete(id);
return TRUE;
}
EXPORT void eventHTML(long id, long source, long eventtype, void *params)
{
Instance instance = id == -1 ? NULL : find(id);
struct _coords {int x, y;};
Widget child;
int x, y;
if (id == -1) return; /* Not interested in */
/* events to class */
/* debug("HTML viewer %ld received event %ld from %ld\n",
id, eventtype, source); */
if (eventtype == POINT_SELECT
&& (child = id_to_widget(instance, source)) != NULL) {
x = ((struct _coords *) params)->x;
y = ((struct _coords *) params)->y;
XfwfPassClick(instance->w, child, x, y);
}
}