aboutsummaryrefslogtreecommitdiff
path: root/vendor/x11iraf/obm/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/x11iraf/obm/html.c')
-rw-r--r--vendor/x11iraf/obm/html.c1534
1 files changed, 1534 insertions, 0 deletions
diff --git a/vendor/x11iraf/obm/html.c b/vendor/x11iraf/obm/html.c
new file mode 100644
index 00000000..3679a7a9
--- /dev/null
+++ b/vendor/x11iraf/obm/html.c
@@ -0,0 +1,1534 @@
+/* Copyright(c) 1993 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <ObmP.h>
+#include "widget.h"
+
+/*
+ * HTML widget class (a subclass of Widget).
+ * -------------------------------------------------------------------------
+ * The HTML (hypertext markup language) widget displays a block of HTML
+ * formatted text, the "document" to be displayed. The text consists of a
+ * mixture of text to be displayed and embedded formatting directives. The
+ * text may also contain "hot links" pointing to other HTML-formatted
+ * documents.
+ *
+ * setText text [target [header_text [footer_text]]]
+ * text = getText [format [font]]
+ * retestAnchors
+ *
+ * id = positionToId x y
+ * idToPosition id x y
+ * anchorToPosition name x y
+ * id = anchorToId name
+ * gotoId id
+ *
+ * n = getHRefs list
+ * n = getImageSrcs list
+ * n = getLinks list
+ *
+ * setSelection start end
+ * text = getSelection start end
+ * clearSelection
+ *
+ * searchText pattern start end [direction [search_type]]
+ *
+ * addCallback procedure-name [callback-type]
+ * deleteCallback procedure-name [callback-type]
+ *
+ * The possible callback types and their callback arguments are as follows.
+ *
+ * anchor widget cbtype event text href element_id
+ * testAnchor widget cbtype href
+ * submitForm widget cbtype event attrs href method enctype encentity
+ * link widget cbtype href role
+ * pointerMotion widget cbtype href
+ *
+ * See the comments below for further details on the callback types and their
+ * arguments.
+ *
+ * All a "hot link" is to the HTML widget is a document object containing a
+ * HREF which causes a callback when selected by the user viewing the document.
+ * It is up to the application using the HTML widget to define what the meaning
+ * of an HREF is.
+ *
+ * This version of the HTML widget binding does not yet support inline images.
+ */
+
+#define CB_Anchor 1
+#define CB_TestAnchor 2
+#define CB_PointerMotion 3
+#define CB_SubmitForm 4
+#define CB_Link 5
+
+/* HTML class instance descriptor. */
+struct htmlPrivate {
+ ObmCallback callback_list;
+};
+
+typedef struct htmlPrivate *HTMLPrivate;
+
+struct htmlObject {
+ struct obmObjectCore core;
+ struct widgetPrivate widget;
+ struct htmlPrivate html;
+};
+
+typedef struct htmlObject *HTMLObject;
+
+/* HTML class class record private data. */
+typedef struct {
+ /* standard MsgContext fields. */
+ Tcl_Interp *tcl; /* class interpreter */
+ ObmObject object[MAX_LEVELS]; /* object which received last message */
+ int level;
+
+ /* HTML specific fields. */
+ /* (none) */
+} htmlClassData, *HTMLClassData;
+
+
+void HTMLDestroy();
+void HTMLClassDestroy();
+ObmObject HTMLCreate();
+
+static int htmlSetText(), htmlGetText(), htmlGetHRefs();
+static int htmlGetImageSrcs(), htmlGetLinks();
+static int htmlRetestAnchors(), htmlPositionToId(), htmlIdToPosition();
+static int htmlAnchorToPosition(), htmlAnchorToId();
+static int htmlGotoId(), htmlAddCallback(), htmlDeleteCallback();
+static int htmlSetSelection(), htmlGetSelection(), htmlClearSelection();
+static int htmlSearchText();
+
+static void anchorCallback(), pointerMotionCallback();
+static void submitFormCallback(), linkCallback();
+static char *cb_encode(), *makeList();
+static int testAnchorCallback();
+static void cb_error();
+static int cb_decode();
+extern long strtol();
+
+
+/* HTMLClassInit -- Initialize the class record for the HTML widget class.
+ */
+void
+HTMLClassInit (obm, classrec)
+ObmContext obm;
+register ObjClassRec classrec;
+{
+ register HTMLClassData gcd;
+ register Tcl_Interp *tcl;
+ register ClientData c_gcd;
+
+ /* Install the class methods. */
+ classrec->ClassDestroy = HTMLClassDestroy;
+ classrec->Create = (ObmFunc) HTMLCreate;
+ classrec->Destroy = HTMLDestroy;
+ classrec->Evaluate = WidgetEvaluate;
+
+ /* The HTML widget subclass has its own command set hence has its
+ * own interpreter. The widget will respond both to all the commands
+ * defined here, and to all the commands implemented by the base
+ * Widget class.
+ */
+ if (!classrec->class_data) {
+ gcd = (HTMLClassData) XtCalloc (1, sizeof (htmlClassData));
+ gcd->tcl = tcl = Tcl_CreateInterp();
+ classrec->class_data = (XtPointer) gcd;
+ c_gcd = (ClientData)gcd;
+ gcd->level = 0;
+
+ Tcl_CreateCommand (tcl,
+ "addCallback", htmlAddCallback, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "deleteCallback", htmlDeleteCallback, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setText", htmlSetText, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getText", htmlGetText, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "positionToId", htmlPositionToId, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "idToPosition", htmlIdToPosition, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "anchorToPosition", htmlAnchorToPosition, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "anchorToId", htmlAnchorToId, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "gotoId", htmlGotoId, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getHRefs", htmlGetHRefs, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getImageSrcs", htmlGetImageSrcs, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getLinks", htmlGetLinks, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "retestAnchors", htmlRetestAnchors, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "setSelection", htmlSetSelection, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "getSelection", htmlGetSelection, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "clearSelection", htmlClearSelection, c_gcd, NULL);
+ Tcl_CreateCommand (tcl,
+ "searchText", htmlSearchText, c_gcd, NULL);
+ }
+}
+
+
+/* HTMLClassDestroy -- Custom destroy procedure for the HTML class.
+ */
+void
+HTMLClassDestroy (obm, classrec)
+ObmContext obm;
+register ObjClassRec classrec;
+{
+ register HTMLClassData gcd = (HTMLClassData) classrec->class_data;
+
+ if (gcd) {
+ if (gcd->tcl)
+ Tcl_DeleteInterp (gcd->tcl);
+ XtFree ((char *)gcd);
+ classrec->class_data = NULL;
+ }
+}
+
+
+/* HTMLCreate -- Create an instance of a HTML object.
+ */
+ObmObject
+HTMLCreate (obm, name, classrec, parent, a_args, a_nargs)
+ObmContext obm;
+char *name;
+ObjClassRec classrec;
+char *parent;
+ArgList a_args;
+int a_nargs;
+{
+ register HTMLObject obj;
+ register Widget w;
+ Arg args[128];
+ int nargs = 0;
+
+ for (nargs = 0; nargs < a_nargs; nargs++)
+ args[nargs] = a_args[nargs];
+
+ XtSetArg (args[nargs], WbNpreviouslyVisitedTestFunction,
+ (long)testAnchorCallback); nargs++;
+ XtSetArg (args[nargs], WbNpointerMotionCallback,
+ (long)pointerMotionCallback); nargs++;
+
+ obj = (HTMLObject) WidgetCreate (obm, name,classrec,parent,args,nargs);
+ if (obj == NULL)
+ return (NULL);
+ obj = (HTMLObject) XtRealloc ((char *)obj, sizeof(struct htmlObject));
+ if (obj == NULL)
+ return (NULL);
+
+ w = obj->widget.w;
+ /* register_image_resolution_function (w); */
+ XtAddCallback (w, WbNanchorCallback, anchorCallback, (XtPointer)obj);
+ XtAddCallback (w, WbNlinkCallback, linkCallback, (XtPointer)obj);
+ XtAddCallback (w, WbNsubmitFormCallback, submitFormCallback,
+ (XtPointer)obj);
+
+ XtSetArg (args[0], WbNpreviouslyVisitedTestData, obj);
+ XtSetArg (args[1], WbNpointerMotionData, obj);
+ XtSetValues (w, args, 2);
+
+ /* Initialize HTMLPrivate instance structure. */
+ obj->html.callback_list = NULL;
+
+ return ((ObmObject) obj);
+}
+
+
+/* HTMLDestroy -- Destroy an instance of a HTML object.
+ */
+void
+HTMLDestroy (object)
+ObmObject object;
+{
+ HTMLObject obj = (HTMLObject) object;
+ ObjClassRec classrec = obj->core.classrec;
+ register HTMLClassData gcd = (HTMLClassData) classrec->class_data;
+ register ObmCallback cb, cb_next;
+ ObmContext obm = obj->widget.obm;
+ Widget w = obj->widget.w;
+
+ /* Destroy the object in the second final call to Destroy. */
+ if (!obj->core.being_destroyed++)
+ return;
+
+ /* Free any HTML callback descriptors. */
+ for (cb = obj->html.callback_list; cb; cb = cb_next) {
+ cb_next = cb->next;
+
+ XtFree ((char *)cb);
+ }
+
+ WidgetDestroy (object);
+}
+
+
+/*
+ * HTML class functions.
+ * -----------------------
+ */
+
+
+/* setText -- Set the text to be displayed in the HTML widget.
+ *
+ * Usage: setText text [target [header_text [footer_text]]]
+ *
+ * If a target anchor is given the text will be positioned to view the
+ * given anchor. The target anchor may be specified either by name or by
+ * its element_id (tag number within the document, e.g. as returned in the
+ * anchor callback). If any HTML-formatted header or footer text is given
+ * this will be displayed before or after the document passed in as "text".
+ */
+static int
+htmlSetText (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ ObmContext obm = wp->obm;
+ char *text, *target_anchor;
+ char *header_text, *footer_text;
+ int element_id;
+
+ text = (argc > 1) ? argv[1] : NULL;
+ target_anchor = (argc > 2) ? argv[2] : NULL;
+ header_text = (argc > 3) ? argv[3] : NULL;
+ footer_text = (argc > 4) ? argv[4] : NULL;
+ element_id = target_anchor ? atoi (target_anchor) : 0;
+
+ HTMLSetText (wp->w, text,
+ header_text, footer_text, element_id, target_anchor, NULL);
+
+ return (TCL_OK);
+}
+
+
+/* getText -- Get the text of the document currently being displayed.
+ *
+ * Usage: text = getText [format [font]]
+ *
+ * The optional format argument determines the type of text to be returned.
+ * The possible values are as follows.
+ *
+ * simple No formatting other than indents.
+ * pretty Simple formatting.
+ * postscript Return formatted Postscript.
+ *
+ * The default output format is simple. If Postscript output is selected
+ * the font can be selected from one of the following:
+ *
+ * times Times
+ * helvetica Helvetica
+ * schoolbook New century schoolbook
+ * lucida Lucida Bright
+ *
+ * The default Postscript font is Times.
+ */
+static int
+htmlGetText (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ char *text, *format, *font;
+ int pretty = 0;
+
+ format = (argc > 1) ? argv[1] : "simple";
+ font = (argc > 2) ? argv[2] : "times";
+
+ if (strcmp (format, "simple") == 0)
+ pretty = 0;
+ else if (strcmp (format, "pretty") == 0)
+ pretty = 1;
+ else if (strcmp (format, "postscript") == 0) {
+ if (strcmp (font, "times") == 0)
+ pretty = 2;
+ else if (strcmp (font, "helvetica") == 0)
+ pretty = 3;
+ else if (strcmp (font, "schoolbook") == 0)
+ pretty = 4;
+ else if (strcmp (font, "lucida") == 0)
+ pretty = 5;
+ else
+ pretty = 2;
+ }
+
+ if (text = HTMLGetText (wp->w, pretty)) {
+ Tcl_SetResult (wp->obm->tcl, text, TCL_VOLATILE);
+ free (text);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* positionToId -- Return the element id of the HTML element nearest to the
+ * given position x,y.
+ *
+ * Usage: id = positionToId x y
+ *
+ * If there is no element at the given position the first element in the
+ * current line is returned. If we are not positioned to a line, either the
+ * beginning or the end of the document is returned.
+ */
+static int
+htmlPositionToId (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ int element_id, x, y;
+ char buf[SZ_NUMBER];
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ x = atoi (argv[1]);
+ y = atoi (argv[2]);
+ element_id = HTMLPositionToId (wp->w, x, y);
+
+ sprintf (buf, "%d", element_id);
+ Tcl_SetResult (wp->obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* idToPosition -- Return the position of an HTML element given its
+ * element id.
+ *
+ * Usage: idToPosition id x y
+ *
+ * If there is no element with the given element id false is returned and
+ * the coordinates x,y are undefined.
+ */
+static int
+htmlIdToPosition (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ int status, element_id, x, y;
+ char buf[SZ_NUMBER];
+ char *s_x, *s_y;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ element_id = atoi (argv[1]);
+ s_x = (argc > 2) ? argv[2] : NULL;
+ s_y = (argc > 3) ? argv[3] : NULL;
+ status = HTMLIdToPosition (wp->w, element_id, &x, &y);
+
+ if (status < 0)
+ Tcl_SetResult (obm->tcl, FALSESTR, TCL_STATIC);
+ else {
+ if (s_x) {
+ sprintf (buf, "%d", x);
+ if ((Tcl_SetVar (obm->tcl, s_x, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ }
+ if (s_y) {
+ sprintf (buf, "%d", y);
+ if ((Tcl_SetVar (obm->tcl, s_y, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ }
+ Tcl_SetResult (obm->tcl, TRUESTR, TCL_STATIC);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* anchorToPosition -- Return the position of the named anchor.
+ *
+ * Usage: bool = anchorToPosition anchor [x y]
+ *
+ * If there is no anchor with the given name false is returned and the
+ * coordinates x,y are undefined.
+ */
+static int
+htmlAnchorToPosition (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ char *anchor, *s_x, *s_y;
+ char buf[SZ_NUMBER];
+ int status, x, y;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ anchor = argv[1];
+ s_x = (argc > 2) ? argv[2] : NULL;
+ s_y = (argc > 3) ? argv[3] : NULL;
+ status = HTMLAnchorToPosition (wp->w, anchor, &x, &y);
+
+ if (status < 0)
+ Tcl_SetResult (obm->tcl, FALSESTR, TCL_STATIC);
+ else {
+ if (s_x) {
+ sprintf (buf, "%d", x);
+ if ((Tcl_SetVar (obm->tcl, s_x, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ }
+ if (s_y) {
+ sprintf (buf, "%d", y);
+ if ((Tcl_SetVar (obm->tcl, s_y, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ }
+ Tcl_SetResult (obm->tcl, TRUESTR, TCL_STATIC);
+ }
+
+ return (TCL_OK);
+}
+
+
+/* anchorToId -- Return the element id of the named anchor.
+ *
+ * Usage: id = anchorToId anchor
+ *
+ * If there is no anchor with the given name false is returned.
+ */
+static int
+htmlAnchorToId (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ char buf[SZ_NUMBER];
+ int element_id;
+ char *anchor;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ anchor = argv[1];
+ element_id = HTMLAnchorToId (wp->w, anchor);
+
+ sprintf (buf, "%d", element_id);
+ Tcl_SetResult (wp->obm->tcl, buf, TCL_VOLATILE);
+
+ return (TCL_OK);
+}
+
+
+/* gotoId -- Position to the given element given its element id.
+ *
+ * Usage: gotoId element_id
+ *
+ * An id of zero means go to the top of the document.
+ */
+static int
+htmlGotoId (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ int element_id;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ element_id = atoi (argv[1]);
+ HTMLGotoId (wp->w, element_id);
+
+ return (TCL_OK);
+}
+
+
+/* getHRefs -- Get a list of the HREFs of all the active anchors in the
+ * document being displayed.
+ *
+ * Usage: n = getHRefs list
+ *
+ * The number of HREFs is returned as the function value; zero is returned
+ * if there are no HREFs, in which case "list" is undefined. If the document
+ * has HREFs on output list will contain a list of HREFs in the form { {HREF1}
+ * {HREF2} ... {HREFn} }.
+ *
+ * An HREF is a hypertext reference, i.e. hot-link or hypertext link to
+ * some other hypertext document that can be referenced by clicking on an
+ * anchor in the document being displayed.
+ */
+static int
+htmlGetHRefs (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ char *a_list, *lbuf, **list;
+ char buf[SZ_NUMBER];
+ int n;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ else
+ a_list = argv[1];
+
+ if (list = HTMLGetHRefs (wp->w, &n)) {
+ if (!(lbuf = makeList (list, n))) {
+ free ((char *)list);
+ return (TCL_ERROR);
+ }
+
+ if ((Tcl_SetVar (obm->tcl, a_list, lbuf, 0)) == NULL) { /* MF024 */
+ free ((char *)list);
+ XtFree (lbuf);
+ return (TCL_ERROR);
+ }
+
+ free ((char *)list);
+ XtFree (lbuf);
+ } else
+ n = 0;
+
+ sprintf (buf, "%d", n);
+ Tcl_SetResult (wp->obm->tcl, buf, TCL_VOLATILE);
+ return (TCL_OK);
+}
+
+
+/* getImageSrcs -- Get a list of the image sources (SRC=) for all the
+ * inline images referenced by the document being displayed.
+ *
+ * Usage: n = getImageSrcs list
+ *
+ * The number of SRCs is returned as the function value; zero is returned
+ * if there are no SRCs, in which case "list" is undefined. If the document
+ * has SRCs on output the list will contain a list of SRCs in the form
+ * { {SRC1} {SRC2} ... {SRCn} }.
+ *
+ * A SRC is a HREF pointing to an image file.
+ */
+static int
+htmlGetImageSrcs (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ char *a_list, *lbuf, **list;
+ char buf[SZ_NUMBER];
+ int n;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ else
+ a_list = argv[1];
+
+ if (list = HTMLGetImageSrcs (wp->w, &n)) {
+ if (!(lbuf = makeList (list, n))) {
+ free ((char *)list);
+ return (TCL_ERROR);
+ }
+
+ if ((Tcl_SetVar (obm->tcl, a_list, lbuf, 0)) == NULL) { /* MF024 */
+ free ((char *)list);
+ XtFree (lbuf);
+ return (TCL_ERROR);
+ }
+
+ free ((char *)list);
+ XtFree (lbuf);
+ } else
+ n = 0;
+
+ sprintf (buf, "%d", n);
+ Tcl_SetResult (wp->obm->tcl, buf, TCL_VOLATILE);
+ return (TCL_OK);
+}
+
+
+/* getLinks -- Get a list of the link tags (<LINK>) referenced by the
+ * document being displayed.
+ *
+ * Usage: n = getLinks list
+ *
+ * The number of links is returned as the function value; zero is returned
+ * if there are no links, in which case "list" is undefined. If there are
+ * any links the returned list will have the format { {{href} {role}} ...}
+ * where the structure {{href} {role}} describes each link.
+ */
+static int
+htmlGetLinks (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ char *a_list, *lbuf;
+ char buf[SZ_NUMBER];
+ LinkInfo *list;
+ int nchars, n;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+ else
+ a_list = argv[1];
+
+ if (list = HTMLGetLinks (wp->w, &n)) {
+ register char *ip, *op;
+ register int i;
+
+ /* Determine how much storage we need for the list. */
+ for (i=0, nchars=0; i < n; i++) {
+ nchars += strlen (list[i].href) + 4;
+ nchars += strlen (list[i].role) + 4;
+ }
+ nchars += 5;
+
+ /* Get the storage. */
+ if (!(lbuf = op = XtMalloc (nchars))) {
+ free ((char *)list);
+ return (TCL_ERROR);
+ }
+
+ /* Encode the list as a Tcl list of lists. */
+ *op++ = '{'; *op++ = ' ';
+ for (i=0; i < n; i++) {
+ *op++ = '{';
+ *op++ = '{';
+ for (ip=list[i].href; ip && *ip; )
+ *op++ = *ip++;
+ *op++ = '}'; *op++ = ' ';
+ *op++ = '{';
+ for (ip=list[i].role; ip && *ip; )
+ *op++ = *ip++;
+ *op++ = '}';
+ *op++ = '}'; *op++ = ' ';
+ }
+ *op++ = '}';
+ *op++ = '\0';
+
+ if ((Tcl_SetVar (obm->tcl, a_list, lbuf, 0)) == NULL) { /* MF024 */
+ free ((char *)list);
+ XtFree (lbuf);
+ return (TCL_ERROR);
+ }
+
+ free ((char *)list);
+ XtFree (lbuf);
+ } else
+ n = 0;
+
+ sprintf (buf, "%d", n);
+ Tcl_SetResult (wp->obm->tcl, buf, TCL_VOLATILE);
+ return (TCL_OK);
+}
+
+
+/* makeList -- Take a list of NULL terminated strings and turn it into a
+ * Tcl list of strings.
+ */
+static char *
+makeList (list, n)
+char **list;
+int n;
+{
+ register char *ip, *op;
+ register int i;
+ int nchars;
+ char *buf;
+
+ /* Determine how much storage we need for the list. */
+ for (i=0, nchars=0; i < n; i++)
+ nchars += strlen (list[i]) + 4;
+ nchars += 5;
+
+ /* Get the storage. */
+ if (!(buf = op = XtMalloc (nchars))) {
+ free ((char *)list);
+ return (NULL);
+ }
+
+ /* Encode the list as a Tcl list of strings. */
+ *op++ = '{'; *op++ = ' ';
+ for (i=0; i < n; i++) {
+ *op++ = '{';
+ for (ip=list[i]; ip && *ip; )
+ *op++ = *ip++;
+ *op++ = '}'; *op++ = ' ';
+ }
+ *op++ = '}';
+ *op++ = '\0';
+
+ return (buf);
+}
+
+
+/* retestAnchors -- Test each anchor and update the display to indicate
+ * the current status of the anchor.
+ *
+ * Usage: retestAnchors
+ *
+ * retestAnchors should be called after loading new text into a widget,
+ * or when the status of one or more anchors has changed, e.g. after a
+ * given URL has been visited.
+ */
+static int
+htmlRetestAnchors (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+
+ HTMLRetestAnchors (wp->w, NULL, 0);
+ return (TCL_OK);
+}
+
+
+/* setSelection -- Set the current text selection to the text bracketed by
+ * the input start and end element refs.
+ *
+ * Usage: setSelection start end
+ *
+ * "start" and "end" are elements refs such as returned by searchText.
+ * An element ref is a structure of the form {element_id offset} specifying
+ * the element id within the document, and the character offset within
+ * that element.
+ */
+static int
+htmlSetSelection (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ ElementRef start, end;
+ char *ip = (char *)NULL;
+
+ if (argc < 3)
+ return (TCL_ERROR);
+
+ ip = (char *)NULL;
+ start.id = strtol (&argv[1][1], &ip, 0);
+ start.pos = strtol (ip, &ip, 0);
+ if (ip == argv[1])
+ return (TCL_ERROR);
+
+ ip = (char *)NULL;
+ end.id = strtol (&argv[2][1], &ip, 0);
+ end.pos = strtol (ip, &ip, 0);
+ if (ip == argv[2])
+ return (TCL_ERROR);
+
+ HTMLSetSelection (wp->w, &start, &end);
+ return (TCL_OK);
+}
+
+
+/* getSelection -- Get the selected text, if any.
+ *
+ * Usage: text = getSelection
+ *
+ * An empty string is returned if there is no current text selection.
+ */
+static int
+htmlGetSelection (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ char *text, *start, *end, *insert;
+
+ text = HTMLGetTextAndSelection (wp->w, &start, &end, &insert);
+ if (text && start) {
+ int nchars = end - start + 1;
+ start[nchars] = '\0';
+ Tcl_SetResult (wp->obm->tcl, start, TCL_VOLATILE);
+ }
+
+ if (text)
+ free (text);
+ return (TCL_OK);
+}
+
+
+/* clearSelection -- Clear the current selection, if any.
+ *
+ * Usage: clearSelection
+ */
+static int
+htmlClearSelection (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+
+ HTMLClearSelection (wp->w);
+ return (TCL_OK);
+}
+
+
+/* searchText -- Search the document for the given pattern.
+ *
+ * Usage: bool = searchText pattern start end [direction [search_type]]
+ *
+ * direction "forward" or "backward"
+ * search_type "caseSensitive" or "caseless"
+ *
+ * If the search is successful start and end are set to the element refs
+ * of the matched region and the function returns a true (nonzero) value.
+ * False is returned if the search fails. An element ref is a structure of
+ * the form {element_id offset} specifying the element id within the document,
+ * and the character offset within that element. The search will automatically
+ * wrap around the page if not found initially.
+ *
+ */
+static int
+htmlSearchText (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ register HTMLClassData gcd = (HTMLClassData) msg;
+ HTMLObject obj = (HTMLObject) gcd->object[gcd->level];
+ register WidgetPrivate wp = &obj->widget;
+ ObmContext obm = obj->widget.obm;
+ char *pattern, *a_start, *a_end;
+ int backward = 0, caseless = 1;
+ static ElementRef start, end;
+ static char patstr[64];
+ int status, again = 1;
+
+ if (argc < 4)
+ return (TCL_ERROR);
+
+ pattern = argv[1];
+ a_start = argv[2];
+ a_end = argv[3];
+ backward = 0;
+ if (argc > 4)
+ backward = (strcmp (argv[4], "backward") == 0);
+ caseless = 0;
+ if (argc > 5)
+ caseless = (strcmp (argv[5], "caseless") == 0);
+
+ /* See whether the pattern has changed and we need to reset the
+ * start and end element refs.
+ */
+ if (strcmp (pattern, patstr) != 0) {
+retry: start.id = start.pos = 0;
+ end.id = end.pos = 0;
+ strcpy (patstr, "");
+ again = 0;
+ }
+
+ /* Do the search. */
+ status = HTMLSearchText (wp->w, pattern,
+ &start, &end, backward, caseless);
+
+ if (status == 1) {
+ char buf[SZ_LINE];
+ sprintf (buf, "{%d %d}", start.id, start.pos);
+ if ((Tcl_SetVar (obm->tcl, a_start, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ sprintf (buf, "{%d %d}", end.id, end.pos);
+ if ((Tcl_SetVar (obm->tcl, a_end, buf, 0)) == NULL) /* MF024 */
+ return (TCL_ERROR);
+ Tcl_SetResult (wp->obm->tcl, TRUESTR, TCL_STATIC);
+ } else {
+ if (again == 1)
+ goto retry;
+ Tcl_SetResult (wp->obm->tcl, FALSESTR, TCL_STATIC);
+ }
+
+ /* Save the pattern string so we can reset later if it changes. */
+ strcpy (patstr, pattern);
+
+ return (TCL_OK);
+}
+
+
+/* AddCallback -- Post a callback for a HTML widget event.
+ *
+ * Usage: addCallback procedure-name [callback-type]
+ *
+ * The recognized HTML callbacks are
+ *
+ * anchor Called to load a new URL.
+ *
+ * testAnchor Called to test whether a given URL has
+ * been previously visited.
+ *
+ * pointerMotion Called when the pointer enters an object
+ * which has a URL.
+ *
+ * submitForm Called when a form is submitted from within
+ * the document being viewed.
+ *
+ * link Called when a <LINK> tag is encountered
+ * while loading text.
+ *
+ * The default callback type is "anchor", which is called when the user
+ * selects a new URL while viewing a document.
+ */
+static int
+htmlAddCallback (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ HTMLObject obj = (HTMLObject) msg->object[msg->level];
+ register WidgetPrivate wp = &obj->widget;
+ register HTMLPrivate hp = &obj->html;
+ register Widget w = wp->w;
+ char *userproc, *callback_type;
+ ObmCallback cb, new;
+ int type;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ userproc = argv[1];
+ callback_type = (argc > 2) ? argv[2] : "anchor";
+ if (!(type = cb_decode (callback_type)))
+ return (TCL_ERROR);
+
+ /* Initialize callback descriptor. */
+ new = (ObmCallback) XtCalloc (1, sizeof (obmCallback));
+ new->u.obj = (ObmObject) obj;
+ new->callback_type = type;
+ strncpy (new->name, userproc, SZ_NAME);
+
+ /* Append descriptor to callback list for widget. */
+ for (cb = hp->callback_list; cb && cb->next; cb = cb->next)
+ ;
+ if (cb)
+ cb->next = new;
+ else
+ hp->callback_list = new;
+
+ return (TCL_OK);
+}
+
+
+/* DeleteCallback -- Delete a HTML callback.
+ *
+ * Usage: deleteCallback procedure [callback_type]
+ *
+ * If a callback type is specified all entries of type callback_type for
+ * the named procedure are deleted, else all entries of any type for the
+ * named procedure are deleted.
+ */
+static int
+htmlDeleteCallback (msg, tcl, argc, argv)
+MsgContext msg;
+Tcl_Interp *tcl;
+int argc;
+char **argv;
+{
+ HTMLObject obj = (HTMLObject) msg->object[msg->level];
+ register HTMLPrivate hp = &obj->html;
+ register ObmCallback cb, prev, next;
+ char *procedure, *callback_type;
+ int type;
+
+ if (argc < 2)
+ return (TCL_ERROR);
+
+ procedure = argv[1];
+ callback_type = (argc > 2) ? argv[2] : NULL;
+ type = callback_type ? cb_decode(callback_type) : 0;
+
+ /* Locate and delete procedure entry in callback list. */
+ for (prev=NULL, cb=hp->callback_list; cb; prev=cb, cb=next) {
+ next = cb->next;
+ if (strcmp (cb->name, procedure) == 0 &&
+ (!type || cb->callback_type == type)) {
+ if (prev)
+ prev->next = next;
+ else
+ hp->callback_list = next;
+ XtFree ((char *)cb);
+ }
+ }
+
+ return (TCL_OK);
+}
+
+
+/* anchorCallback -- Callback procedure called by the HTML widget when an
+ * anchor (URL) is selected.
+ *
+ * Calling sequence:
+ *
+ * userproc widget cbtype event text href element_id
+ *
+ * All callbacks registered with the current widget for the anchor callback
+ * are called in the order in which they were registered.
+ */
+static void
+anchorCallback (w, client_data, call_data)
+Widget w;
+XtPointer client_data;
+XtPointer call_data;
+{
+ register char *ip, *op;
+ register ObmCallback cb;
+ register WbAnchorCallbackData *ap = (WbAnchorCallbackData *)call_data;
+ HTMLObject obj = (HTMLObject) client_data;
+ ObmContext obm = obj->widget.obm;
+ char *text, *href, *none = "none";
+ char event_type[SZ_LINE];
+ char element_id[SZ_NUMBER];
+ int status;
+
+ text = ap->text ? ap->text : none;
+ href = ap->href ? ap->href : none;
+ sprintf (element_id, "%d", ap->element_id);
+ op = event_type;
+
+ /* Compose the event type information. This is the name of the
+ * key typed, or "Button1", "Button2", etc. for the mouse buttons.
+ */
+ switch (ap->event->type) {
+ case KeyPress:
+ case KeyRelease:
+ { XKeyPressedEvent *ev = (XKeyPressedEvent *) ap->event;
+ char buf[20];
+ int n;
+
+ if ((n = XLookupString(ev,buf,sizeof(buf),NULL,NULL)) > 0) {
+ for (ip=buf; --n >= 0; )
+ if (*ip <= ' ') {
+ *op++ = '^';
+ *op++ = *ip++ + 'A' - 1;
+ } else if (isprint (*ip)) {
+ *op++ = *ip++;
+ } else
+ ip++;
+ } else {
+ /* This case occurs when only a modifier is typed. */
+ for (ip = "??"; *op++ = *ip++; )
+ ;
+ }
+ *op = '\0';
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ { XButtonPressedEvent *ev = (XButtonPressedEvent *) ap->event;
+ sprintf (op, "Button%d", ev->button);
+ }
+ break;
+ default:
+ strcpy (event_type, "unknown");
+ }
+
+ /* Call any registered callback functions. */
+ for (cb = obj->html.callback_list; cb; cb = cb->next) {
+ if (cb->callback_type != CB_Anchor)
+ continue;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ cb_encode(cb->callback_type), " ",
+ event_type, " ",
+ "{", text, "} ",
+ "{", href, "} ",
+ element_id,
+ NULL);
+
+ if (status != TCL_OK)
+ cb_error (obm, cb);
+ }
+}
+
+
+/* testAnchorCallback -- Callback procedure called by the HTML widget to
+ * test whether a given anchor (URL) has been previously visited.
+ *
+ * Calling sequence:
+ *
+ * userproc widget cbtype href
+ *
+ * A nonzero value should be returned by the userproc if the given anchor
+ * has been visited previously, otherwise a zero should be returned.
+ */
+static int
+testAnchorCallback (w, client_data, href)
+Widget w;
+XtPointer client_data;
+char *href;
+{
+ register ObmCallback cb;
+ register HTMLObject obj = (HTMLObject) client_data;
+ register ObmContext obm = obj->widget.obm;
+ int status, retval = 0;
+
+ /* Call any registered callback functions. */
+ for (cb = obj->html.callback_list; cb; cb = cb->next) {
+ if (cb->callback_type != CB_TestAnchor)
+ continue;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ cb_encode(cb->callback_type), " ",
+ "{", href, "} ",
+ NULL);
+
+ if (status != TCL_OK)
+ cb_error (obm, cb);
+ else if (atoi (obm->tcl->result))
+ retval = 1;
+ }
+
+ return (retval);
+}
+
+
+/* submitFormCallback -- Callback procedure called by the HTML widget when
+ * a form is submitted from the document.
+ *
+ * Calling sequence:
+ *
+ * userproc widget cbtype event attrs href method enctype encentity
+ *
+ * "widget" is the name of the HTML widget which generated the callback.
+ * "cbtype" is the type of callback, i.e., "submitForm". "event" is the
+ * key/button event which triggered the callback, e.g. "Button1".
+ *
+ * "attrs" is a list of attribute-value pairs defining the contents of the
+ * form. That is, a list of the form { {attr1 value1} {attr2 value2} ... }.
+ *
+ * The final block of arguments deal with how to process or deliver the form.
+ * "href", "method", "enctype", and "encentity" are strings defined by the
+ * HTML form. The application is free to use these as it wishes, except for
+ * an HTML form query where the meaning of these fields is well defined.
+ * The "href" field is normally the URL to which the form is to be submitted,
+ * while "method" is the method to be used to submit the form.
+ */
+static void
+submitFormCallback (w, client_data, call_data)
+Widget w;
+XtPointer client_data;
+XtPointer call_data;
+{
+ register char *ip, *op;
+ register ObmCallback cb;
+ register WbFormCallbackData *fp = (WbFormCallbackData *)call_data;
+ HTMLObject obj = (HTMLObject) client_data;
+ ObmContext obm = obj->widget.obm;
+
+ char *href, *method, *enctype, *encentity;
+ char *abuf, event_type[SZ_LINE];
+ char *none = "none";
+ int status, i, n;
+
+ href = fp->href ? fp->href : none;
+ method = fp->method ? fp->method : none;
+ enctype = fp->enctype ? fp->enctype : none;
+ encentity = fp->enc_entity ? fp->enc_entity : none;
+ op = event_type;
+
+ /* Compose the event type information. This is the name of the
+ * key typed, or "Button1", "Button2", etc. for the mouse buttons.
+ */
+ switch (fp->event->type) {
+ case KeyPress:
+ case KeyRelease:
+ { XKeyPressedEvent *ev = (XKeyPressedEvent *) fp->event;
+ char buf[20];
+ int n;
+
+ if ((n = XLookupString(ev,buf,sizeof(buf),NULL,NULL)) > 0) {
+ for (ip=buf; --n >= 0; )
+ if (*ip <= ' ') {
+ *op++ = '^';
+ *op++ = *ip++ + 'A' - 1;
+ } else if (isprint (*ip)) {
+ *op++ = *ip++;
+ } else
+ ip++;
+ } else {
+ /* This case occurs when only a modifier is typed. */
+ for (ip = "??"; *op++ = *ip++; )
+ ;
+ }
+ *op = '\0';
+ }
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ { XButtonPressedEvent *ev = (XButtonPressedEvent *) fp->event;
+ sprintf (op, "Button%d", ev->button);
+ }
+ break;
+ default:
+ strcpy (event_type, "unknown");
+ }
+
+ /* Get storage for the attribute list. */
+ for (i=0, n=0; i < fp->attribute_count; i++) {
+ n += strlen (fp->attribute_names[i]);
+ n += strlen (fp->attribute_values[i]);
+ n += 10;
+ }
+ if (!(abuf = XtMalloc (n)))
+ return;
+
+ /* Construct the attribute list.
+ */
+ for (i=0, op=abuf; i < fp->attribute_count; i++) {
+ *op++ = '{';
+
+ *op++ = '{';
+ for (ip = fp->attribute_names[i]; ip && *ip; )
+ *op++ = *ip++;
+ *op++ = '}'; *op++ = ' ';
+
+ *op++ = '{';
+ for (ip = fp->attribute_values[i]; ip && *ip; )
+ *op++ = *ip++;
+ *op++ = '}';
+
+ *op++ = '}'; *op++ = ' ';
+ }
+ *op = '\0';
+
+ /* Call any registered callback functions. */
+ for (cb = obj->html.callback_list; cb; cb = cb->next) {
+ if (cb->callback_type != CB_SubmitForm)
+ continue;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ cb_encode(cb->callback_type), " ",
+ event_type, " ",
+ "{ ", abuf, "} ",
+ href, " ",
+ method, " ",
+ enctype, " ",
+ encentity, " ",
+ NULL);
+
+ if (status != TCL_OK)
+ cb_error (obm, cb);
+ }
+
+ XtFree (abuf);
+}
+
+
+/* linkCallback -- Callback procedure called by the HTML widget when
+ * a <LINK> directive is encountered while loading text into the widget.
+ *
+ * Calling sequence:
+ *
+ * userproc widget cbtype href role
+ *
+ * All callbacks registered with the current widget for the callback
+ * are called in the order in which they were registered.
+ */
+static void
+linkCallback (w, client_data, call_data)
+Widget w;
+XtPointer client_data;
+XtPointer call_data;
+{
+ register char *ip, *op;
+ register ObmCallback cb;
+ LinkInfo *l_info = (LinkInfo *) call_data;
+ HTMLObject obj = (HTMLObject) client_data;
+ ObmContext obm = obj->widget.obm;
+ char *href, *role, *none = "none";
+ int status;
+
+ href = l_info->href ? l_info->href : none;
+ role = l_info->role ? l_info->role : none;
+
+ /* Call any registered callback functions. */
+ for (cb = obj->html.callback_list; cb; cb = cb->next) {
+ if (cb->callback_type != CB_Link)
+ continue;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ cb_encode(cb->callback_type), " ",
+ href, " ",
+ role, " ",
+ NULL);
+
+ if (status != TCL_OK)
+ cb_error (obm, cb);
+ }
+}
+
+
+/* pointerMotionCallback -- Callback procedure called by the HTML widget when
+ * the pointer enters an anchor.
+ *
+ * Calling sequence:
+ *
+ * userproc widget cbtype href
+ */
+static void
+pointerMotionCallback (w, client_data, href)
+Widget w;
+XtPointer client_data;
+char *href;
+{
+ register ObmCallback cb;
+ register HTMLObject obj = (HTMLObject) client_data;
+ register ObmContext obm = obj->widget.obm;
+ int status;
+
+ /* Call any registered callback functions. */
+ for (cb = obj->html.callback_list; cb; cb = cb->next) {
+ if (cb->callback_type != CB_PointerMotion)
+ continue;
+
+ status = Tcl_VarEval (obm->tcl,
+ cb->name, " ",
+ obj->core.name, " ",
+ cb_encode(cb->callback_type), " ",
+ "{", href, "} ",
+ NULL);
+
+ if (status != TCL_OK)
+ cb_error (obm, cb);
+ }
+}
+
+
+/* cb_error -- Convenience routine to return an error from a callback.
+ */
+static void
+cb_error (obm, cb)
+register ObmContext obm;
+register ObmCallback cb;
+{
+ register Tcl_Interp *tcl = obm->tcl;
+ char *errstr = Tcl_GetVar (tcl, "errorInfo", 0);
+ fprintf (stderr, "Error on line %d in %s: %s\n",
+ tcl->errorLine, cb->name,
+ errstr ? errstr : tcl->result);
+}
+
+/* cb_decode -- Convert a callback_type string to a callback type code.
+ */
+static int
+cb_decode (callback_type)
+register char *callback_type;
+{
+ register int type = 0;
+
+ if (strcmp (callback_type, "anchor") == 0)
+ type = CB_Anchor;
+ else if (strcmp (callback_type, "testAnchor") == 0)
+ type = CB_TestAnchor;
+ else if (strcmp (callback_type, "pointerMotion") == 0)
+ type = CB_PointerMotion;
+ else if (strcmp (callback_type, "submitForm") == 0)
+ type = CB_SubmitForm;
+ else if (strcmp (callback_type, "link") == 0)
+ type = CB_Link;
+
+ return (type);
+}
+
+/* cb_encode -- Convert a callback_type string to a callback type code.
+ */
+static char *
+cb_encode (callback_type)
+int callback_type;
+{
+ register char *type = "unknown";
+
+ switch (callback_type) {
+ case CB_Anchor:
+ type = "anchor";
+ break;
+ case CB_TestAnchor:
+ type = "testAnchor";
+ break;
+ case CB_PointerMotion:
+ type = "pointerMotion";
+ break;
+ case CB_SubmitForm:
+ type = "submitForm";
+ break;
+ case CB_Link:
+ type = "link";
+ break;
+ }
+
+ return (type);
+}