2009年5月14日 星期四

Dillo JavaScript experiment patch

diff -r 468e535f1435 config.h.in
--- a/config.h.in    Wed May 13 13:31:37 2009 -0400
+++ b/config.h.in    Thu May 14 23:48:02 2009 +0800
@@ -2,6 +2,9 @@
 
 /* Enable GIF images */
 #undef ENABLE_GIF
+
+/* Enable JavaScript */
+#undef ENABLE_JAVASCRIPT
 
 /* Enable JPEG images */
 #undef ENABLE_JPEG
@@ -14,6 +17,24 @@
 
 /* Define to 1 if you have the header file. */
 #undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `GC_dump' function. */
+#undef HAVE_GC_DUMP
+
+/* Define to 1 if you have the `GC_free' function. */
+#undef HAVE_GC_FREE
+
+/* Define to 1 if you have the `GC_gcollect' function. */
+#undef HAVE_GC_GCOLLECT
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_GC_GC_H
+
+/* Define to 1 if you have the `GC_malloc' function. */
+#undef HAVE_GC_MALLOC
+
+/* Define to 1 if you have the `GC_malloc_atomic' function. */
+#undef HAVE_GC_MALLOC_ATOMIC
 
 /* Define to 1 if you have the `gethostbyname' function. */
 #undef HAVE_GETHOSTBYNAME
@@ -35,6 +56,12 @@
 
 /* Define to 1 if you have the header file. */
 #undef HAVE_PNG_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SEE_H
+
+/* Define to 1 if you have the header file. */
+#undef HAVE_SEE_SEE_H
 
 /* Define to 1 if you have the `setsockopt' function. */
 #undef HAVE_SETSOCKOPT
@@ -102,6 +129,9 @@
 /* Version number of package */
 #undef VERSION
 
+/* Define if you have Boehm GC */
+#undef WITH_BOEHM_GC
+
 /* Use char pointers for newer libiconv */
 #undef inbuf_t
 
diff -r 468e535f1435 configure.in
--- a/configure.in    Wed May 13 13:31:37 2009 -0400
+++ b/configure.in    Thu May 14 23:48:02 2009 +0800
@@ -32,6 +32,8 @@ AC_ARG_ENABLE(jpeg,   [  --disable-jpeg
               enable_jpeg=$enableval, enable_jpeg=yes)
 AC_ARG_ENABLE(gif,    [  --disable-gif           Disable support for GIF images],
               enable_gif=$enableval, enable_gif=yes)
+AC_ARG_ENABLE(javascript, [  --disable-javascript    Disable support for JavaScript],
+              enable_javascript=$enableval, enable_javascript=yes)
 AC_ARG_ENABLE(threaded-dns,[  --disable-threaded-dns  Disable the advantage of a reentrant resolver library],
               enable_threaded_dns=$enableval, enable_threaded_dns=yes)
 AC_ARG_ENABLE(rtfl,   [  --enable-rtfl           Build with rtfl messages])
@@ -183,6 +185,115 @@ fi
 
 if test "x$jpeg_ok" = "xyes"; then
   AC_DEFINE([ENABLE_JPEG], [], [Enable JPEG images])
+fi
+
+dnl ----------------
+dnl Test for libsee
+dnl ----------------
+dnl
+if test "x$enable_javascript" = "xyes"; then
+  AC_MSG_CHECKING([for libsee-config])
+
+dnl Check if the user hasn't set the variable $SEE_CONFIG
+  if test -z "$SEE_CONFIG"; then
+    SEE_CONFIG=`which libsee-config`
+  fi
+
+dnl Check if the libpng-config script was found and is executable
+  if test -n "$SEE_CONFIG" && test -x "$SEE_CONFIG"; then
+    AC_MSG_RESULT([$SEE_CONFIG])
+    see_ok="yes"
+    LIBSEE_CPPFLAGS=`$SEE_CONFIG --cppflags`
+    LIBSEE_LIBS=`$SEE_CONFIG --libs`    
+  else
+    AC_MSG_RESULT([missing])
+    see_ok="no"
+  fi
+
+dnl Try to find libpng even though libpng-config wasn't found
+  if  test "x$see_ok" = "xno"; then
+    AC_CHECK_HEADERS(see.h see/see.h, see_ok=yes && break, see_ok=no)
+
+    if test "x$see_ok" = "xyes"; then
+      old_libs="$LIBS"
+      AC_CHECK_LIB(see, SEE_interpreter_init, see_ok=yes, see_ok=no)
+      LIBS="$old_libs"
+
+      if test "x$see_ok" = "xyes"; then
+        LIBSEE_LIBS="-lsee"
+      fi
+    fi
+
+    if test "x$see_ok" = "xno"; then
+      AC_MSG_WARN([*** No libsee found. Disabling JavaScript ***])
+    fi
+  fi
+fi
+
+if test "x$see_ok" = "xyes"; then
+
+dnl ------------------------------------------------------------
+dnl external libraries
+dnl
+
+AC_ARG_WITH(boehm-gc,
+    AC_HELP_STRING([--with-boehm-gc],
+        [use Boehm-Weiser garbage collector, default=yes]),
+        [with_boehmgc=$withval], [with_boehmgc=yes])
+  if test x"$with_boehmgc" != x"no"; then
+    save_LIBSEE_LIBS="$LIBSEE_LIBS"
+    save_LIBS="$LIBS"
+    save_LDFLAGS="$LDFLAGS"
+    save_CPPFLAGS="$CPPFLAGS"
+    case "$with_boehmgc" in
+     yes)
+        LIBSEE_LIBS="$LIBSEE_LIBS -lgc"
+        LIBS="$LIBS -lgc"
+        ;;
+     *) LIBSEE_LIBS="$LIBSEE_LIBS -L${with_boehmgc}/lib -lgc"
+        LDFLAGS="$LDFLAGS -L${with_boehmgc}/lib"
+        LIBS="$LIBS -lgc"
+        CPPFLAGS="$CPPFLAGS -I${with_boehmgc}/include"
+        ;;
+    esac
+
+      # The following minimum for Boehm GC support:
+      #
+      #   #if WITH_BOEHM_GC
+      #   # include
+      #   GC_INIT();
+      #   GC_MALLOC(...);
+      #   GC_dump();
+      #   GC_gcollect();
+      #   #endif
+
+      have_boehm_gc=yes
+      AC_CHECK_HEADERS([gc/gc.h],,[have_boehm_gc=no])
+      AC_TRY_LINK([#include ],
+        [GC_INIT();
+         GC_MALLOC(1);
+         GC_gcollect();
+        ],,
+        [have_boehm_gc=no])
+      if test x"$have_boehm_gc" = x"yes"; then
+        AC_DEFINE(WITH_BOEHM_GC, [1], [Define if you have Boehm GC])
+        AC_CHECK_FUNCS([GC_malloc GC_gcollect GC_dump GC_malloc_atomic GC_free],
+                        ,[have_boehm_gc=no])
+      else
+          LIBSEE_LIBS="$save_LIBSEE_LIBS"
+          CPPFLAGS="$save_CPPFLAGS"
+      fi
+      LDFLAGS="$save_LDFLAGS"
+      LIBS="$save_LIBS"
+  else
+      have_boehm_gc=no
+  fi
+  AC_MSG_CHECKING([if we can use Boehm GC])
+  AM_CONDITIONAL(WITH_BOEHM_GC, test x"$have_boehm_gc" = x"yes")
+  AC_MSG_RESULT([$have_boehm_gc])
+
+
+  AC_DEFINE([ENABLE_JAVASCRIPT], [], [Enable JavaScript])
 fi
 
 dnl -------------
@@ -491,6 +602,8 @@ AC_SUBST(LIBJPEG_CPPFLAGS)
 AC_SUBST(LIBJPEG_CPPFLAGS)
 AC_SUBST(LIBPNG_LIBS)
 AC_SUBST(LIBPNG_CFLAGS)
+AC_SUBST(LIBSEE_LIBS)
+AC_SUBST(LIBSEE_CPPFLAGS)
 AC_SUBST(LIBZ_LIBS)
 AC_SUBST(LIBSSL_LIBS)
 AC_SUBST(LIBPTHREAD_LIBS)
diff -r 468e535f1435 src/Makefile.am
--- a/src/Makefile.am    Wed May 13 13:31:37 2009 -0400
+++ b/src/Makefile.am    Thu May 14 23:48:02 2009 +0800
@@ -14,7 +14,7 @@ dillo_LDADD = \
     ../dw/libDw-fltk.a \
     ../dw/libDw-core.a \
     ../lout/liblout.a \
-    @LIBJPEG_LIBS@ @LIBPNG_LIBS@ @LIBFLTK_LIBS@ @LIBZ_LIBS@ @LIBICONV_LIBS@
+    @LIBJPEG_LIBS@ @LIBPNG_LIBS@ @LIBFLTK_LIBS@ @LIBZ_LIBS@ @LIBICONV_LIBS@ @LIBSEE_LIBS@
 
 dillo_SOURCES = \
     dillo.cc \
diff -r 468e535f1435 src/form.cc
--- a/src/form.cc    Wed May 13 13:31:37 2009 -0400
+++ b/src/form.cc    Thu May 14 23:48:02 2009 +0800
@@ -24,6 +24,8 @@
 #include "prefs.h"
 #include "nav.h"
 #include "uicmd.hh"
+
+#include "capi.h"
 
 using namespace dw;
 using namespace dw::core;
@@ -95,6 +97,7 @@ class DilloHtmlForm {
                                   Dstr *x, Dstr *y);
 
 public:  //BUG: for now everything is public
+   char *name;
    DilloHtmlMethod method;
    DilloUrl *action;
    DilloHtmlEnc content_type;
@@ -107,7 +110,7 @@ public:  //BUG: for now everything is pu
    DilloHtmlReceiver *form_receiver;
 
 public:
-   DilloHtmlForm (DilloHtml *html,
+   DilloHtmlForm (DilloHtml *html, char *name,
                   DilloHtmlMethod method, const DilloUrl *action,
                   DilloHtmlEnc content_type, const char *charset,
                   bool enabled);
@@ -151,6 +154,7 @@ public:  //BUG: for now everything is pu
    bool init_val;     /* only meaningful for buttons */
    Dstr *file_data;   /* only meaningful for file inputs.
                          TODO: may become a list... */
+   char *onclick;
 
 private:
    void connectTo(DilloHtmlReceiver *form_receiver);
@@ -159,7 +163,7 @@ private:
 
 public:
    DilloHtmlInput (DilloHtmlInputType type, Embed *embed,
-                   const char *name, const char *init_str, bool init_val);
+                   const char *name, const char *init_str, bool init_val, const char *onclick);
    ~DilloHtmlInput ();
    void appendValuesTo(Dlist *values, bool is_active_submit);
    void reset();
@@ -194,12 +198,12 @@ private:
  * Form API
  */
 
-DilloHtmlForm *a_Html_form_new (DilloHtml *html, DilloHtmlMethod method,
+DilloHtmlForm *a_Html_form_new (DilloHtml *html, char *name, DilloHtmlMethod method,
                                 const DilloUrl *action,
                                 DilloHtmlEnc content_type, const char *charset,
                                 bool enabled)
 {
-   return new DilloHtmlForm (html, method, action, content_type, charset, enabled);
+   return new DilloHtmlForm (html, name, method, action, content_type, charset, enabled);
 }
 
 void a_Html_form_delete (DilloHtmlForm *form)
@@ -236,11 +240,11 @@ void a_Html_form_display_hiddens2(void *
  */
 static void Html_add_input(DilloHtml *html, DilloHtmlInputType type,
                            Embed *embed, const char *name,
-                           const char *init_str, bool init_val)
+                           const char *init_str, bool init_val, const char *onclick)
 {
    _MSG("name=[%s] init_str=[%s] init_val=[%d]\n", name, init_str, init_val);
    DilloHtmlInput *input = new DilloHtmlInput(type, embed, name, init_str,
-                                              init_val);
+                                              init_val, onclick);
    if (html->InFlags & IN_FORM) {
       html->getCurrentForm()->addInput(input, type);
    } else {
@@ -292,6 +296,7 @@ static DilloHtmlInput *Html_get_current_
  */
 void Html_tag_open_form(DilloHtml *html, const char *tag, int tagsize)
 {
+   char *name = 0;
    DilloUrl *action;
    DilloHtmlMethod method;
    DilloHtmlEnc content_type;
@@ -309,6 +314,9 @@ void Html_tag_open_form(DilloHtml *html,
    html->InFlags &= ~IN_OPTION;
    html->InFlags &= ~IN_TEXTAREA;
 
+   if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
+      name = dStrdup(attrbuf);
+   }
    method = DILLO_HTML_METHOD_GET;
    if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "method"))) {
       if (!dStrcasecmp(attrbuf, "post")) {
@@ -348,7 +356,7 @@ void Html_tag_open_form(DilloHtml *html,
    }
    if (!charset)
       charset = html->charset;
-   html->formNew(method, action, content_type, charset);
+   html->formNew(name, method, action, content_type, charset);
    dFree(first);
    a_Url_free(action);
 }
@@ -411,7 +419,7 @@ void Html_tag_open_input(DilloHtml *html
    DilloHtmlInputType inp_type;
    Resource *resource = NULL;
    Embed *embed = NULL;
-   char *value, *name, *type, *init_str;
+   char *value, *name, *type, *onclick, *init_str;
    const char *attrbuf, *label;
    bool init_val = false;
    ResourceFactory *factory;
@@ -431,6 +439,7 @@ void Html_tag_open_input(DilloHtml *html
    value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
    name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
    type = a_Html_get_attr_wdef(html, tag, tagsize, "type", "");
+   onclick = a_Html_get_attr_wdef(html, tag, tagsize, "onclick", NULL);
 
    init_str = NULL;
    inp_type = DILLO_HTML_INPUT_UNKNOWN;
@@ -528,7 +537,7 @@ void Html_tag_open_input(DilloHtml *html
 
    if (inp_type != DILLO_HTML_INPUT_UNKNOWN) {
       Html_add_input(html, inp_type, embed, name,
-                     (init_str) ? init_str : "", init_val);
+                     (init_str) ? init_str : "", init_val, onclick);
    }
 
    if (embed != NULL && inp_type != DILLO_HTML_INPUT_IMAGE &&
@@ -554,6 +563,8 @@ void Html_tag_open_input(DilloHtml *html
    if (init_str != value)
       dFree(init_str);
    dFree(value);
+   if(onclick)
+      dFree(onclick);
 }
 
 /*
@@ -562,6 +573,7 @@ void Html_tag_open_input(DilloHtml *html
  */
 void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize)
 {
+   char *name = 0;
    DilloUrl *action;
    Embed *embed;
    const char *attrbuf;
@@ -571,12 +583,15 @@ void Html_tag_open_isindex(DilloHtml *ht
       return;
    }
 
+   if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "name"))) {
+      name = dStrdup(attrbuf);
+   }
    if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "action")))
       action = a_Html_url_new(html, attrbuf, NULL, 0);
    else
       action = a_Url_dup(html->base_url);
 
-   html->formNew(DILLO_HTML_METHOD_GET, action, DILLO_HTML_ENC_URLENCODED,
+   html->formNew(name, DILLO_HTML_METHOD_GET, action, DILLO_HTML_ENC_URLENCODED,
                  html->charset);
    html->InFlags |= IN_FORM;
 
@@ -588,7 +603,7 @@ void Html_tag_open_isindex(DilloHtml *ht
    ResourceFactory *factory = HT2LT(html)->getResourceFactory();
    EntryResource *entryResource = factory->createEntryResource (20,false,NULL);
    embed = new Embed (entryResource);
-   Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE);
+   Html_add_input(html, DILLO_HTML_INPUT_INDEX, embed, NULL, NULL, FALSE, 0);
 
    HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ());
 
@@ -656,7 +671,7 @@ void Html_tag_open_textarea(DilloHtml *h
    /* Readonly or not? */
    if (a_Html_get_attr(html, tag, tagsize, "readonly"))
       textres->setEditable(false);
-   Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false);
+   Html_add_input(html, DILLO_HTML_INPUT_TEXTAREA, embed, name, NULL, false, 0);
 
    HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ());
    dFree(name);
@@ -744,7 +759,7 @@ void Html_tag_open_select(DilloHtml *htm
 
    HT2TB(html)->addWidget (embed, html->styleEngine->backgroundStyle ());
 
-   Html_add_input(html, type, embed, name, NULL, false);
+   Html_add_input(html, type, embed, name, NULL, false, 0);
    a_Html_stash_init(html);
    dFree(name);
 }
@@ -837,7 +852,7 @@ void Html_tag_open_button(DilloHtml *htm
       /* Render the button */
       Widget *page;
       Embed *embed;
-      char *name, *value;
+      char *name, *value, *onclick;
 
       page = new Textblock (prefs.limit_text_width);
       page->setStyle (html->styleEngine->backgroundStyle ());
@@ -857,10 +872,13 @@ void Html_tag_open_button(DilloHtml *htm
 
       value = a_Html_get_attr_wdef(html, tag, tagsize, "value", NULL);
       name = a_Html_get_attr_wdef(html, tag, tagsize, "name", NULL);
+      onclick = a_Html_get_attr_wdef(html, tag, tagsize, "onclick", NULL);
 
-      Html_add_input(html, inp_type, embed, name, value, FALSE);
+      Html_add_input(html, inp_type, embed, name, value, FALSE, onclick);
       dFree(name);
       dFree(value);
+      if(onclick)
+         dFree(onclick);
    }
    dFree(type);
 }
@@ -885,11 +903,13 @@ void Html_tag_close_button(DilloHtml *ht
  * Constructor
  */
 DilloHtmlForm::DilloHtmlForm (DilloHtml *html2,
+                              char *name2,
                               DilloHtmlMethod method2,
                               const DilloUrl *action2,
                               DilloHtmlEnc content_type2,
                               const char *charset, bool enabled)
 {
+   name = name2;
    html = html2;
    method = method2;
    action = a_Url_dup(action2);
@@ -907,6 +927,8 @@ DilloHtmlForm::DilloHtmlForm (DilloHtml
  */
 DilloHtmlForm::~DilloHtmlForm ()
 {
+   if(name)
+      dFree(name);
    a_Url_free(action);
    dFree(submit_charset);
    for (int j = 0; j < inputs->size(); j++)
@@ -937,6 +959,21 @@ void DilloHtmlForm::eventHandler(Resourc
  */
 void DilloHtmlForm::submit(DilloHtmlInput *active_input, EventButton *event)
 {
+  if(active_input->onclick) {
+    //printf("onclick = %s\n", active_input->onclick);
+    bool bRetVal = false;
+    char *s = active_input->onclick;
+    if(strncasecmp("return ", active_input->onclick, 7) == 0) {
+      s = active_input->onclick + 7;
+      bRetVal = true; /*Enable return value check*/
+    }
+    void *p = a_Html_script_run(html, s);
+    if(bRetVal && p == 0)  {
+printf("onClick fail...\n");
+      return;
+    }
+  }
+
    DilloUrl *url = buildQueryUrl(active_input);
    if (url) {
       if (event && event->button == 2) {
@@ -1528,13 +1565,14 @@ void DilloHtmlReceiver::clicked (Resourc
  */
 DilloHtmlInput::DilloHtmlInput (DilloHtmlInputType type2, Embed *embed2,
                                 const char *name2, const char *init_str2,
-                                bool init_val2)
+                                bool init_val2, const char *onclick2)
 {
    type = type2;
    embed = embed2;
    name = (name2) ? dStrdup(name2) : NULL;
    init_str = (init_str2) ? dStrdup(init_str2) : NULL;
    init_val = init_val2;
+   onclick = (onclick2) ? dStrdup(onclick2) : NULL;
    select = NULL;
    switch (type) {
    case DILLO_HTML_INPUT_SELECT:
@@ -1558,6 +1596,8 @@ DilloHtmlInput::~DilloHtmlInput ()
    dStr_free(file_data, 1);
    if (select)
       delete select;
+   if (onclick)
+      dFree(onclick);
 }
 
 /*
@@ -1936,3 +1976,480 @@ static void Html_option_finish(DilloHtml
          a_Html_parse_entities(html, html->Stash->str, html->Stash->len);
    }
 }
+
+/*
+ * File: dom.cc
+ *
+ * Copyright (C) 2009 Steve Chang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+/*
+* Document Object Model
+*/
+
+#if WITH_BOEHM_GC
+# include
+#endif
+
+#include
+
+static struct SEE_interpreter *interp = 0;
+
+/*
+ * Runs the input given by inp, printing any exceptions
+ * to stderr.
+ * This function first establishes a local exception catch context.
+ * Next, it passes the unicode input provider ('inp') to the generic
+ * evaluation procedure SEE_Global_eval which executes the program
+ * text in the ECMAScript global context. This function also examines
+ * the result of the evaluation, being careful to print out exceptions
+ * correctly.
+ * Returns 0 if an exception was uncaught, or 1 if the script ran to
+ * completion.
+ */
+static int
+run_input(struct SEE_input *inp, struct SEE_value *res)
+{
+  struct SEE_value v;
+  SEE_try_context_t ctxt, ctxt2;
+
+  interp->traceback = NULL;
+        SEE_TRY (interp, ctxt) {
+/*
+      if (debugger)
+          debug_eval(interp, debugger, inp, res);
+      else
+*/
+          SEE_Global_eval(interp, inp, res);
+        }
+        if (SEE_CAUGHT(ctxt)) {
+            fprintf(stderr, "exception:\n");
+            SEE_TRY(interp, ctxt2) {
+                SEE_ToString(interp, SEE_CAUGHT(ctxt), &v);
+                fprintf(stderr, "  ");
+                SEE_string_fputs(v.u.string, stderr);
+                fprintf(stderr, "\n");
+#ifndef NDEBUG
+                if (ctxt.throw_file)
+        fprintf(stderr, "  (thrown from %s:%d)\n",
+                        ctxt.throw_file, ctxt.throw_line);
+#endif
+    SEE_PrintContextTraceback(interp, &ctxt, stderr);
+            }
+            if (SEE_CAUGHT(ctxt2)) {
+    /* Exception while printing exception! */
+                fprintf(stderr, "[exception thrown while printing exception");
+    if (ctxt2.throw_file)
+        fprintf(stderr, " at %s:%d",
+            ctxt2.throw_file, ctxt2.throw_line);
+                fprintf(stderr, "]\n");
+      }
+      return 0;
+        }
+        return 1;
+}
+
+class DilloHtmlScript {
+  DilloHtml *html;
+  DilloHtmlScriptType type;
+  DilloUrl *src;
+  char *script;
+  struct SEE_input *input;
+
+public:
+  DilloHtmlScript(DilloHtml *html, DilloHtmlScriptType type, const DilloUrl *src, const char *script);
+  ~DilloHtmlScript();
+
+  void Script(const char *script);
+  void Input();
+};
+
+/*
+ * Called by the network engine to load javascript.
+ */
+
+static void Script_load_callback(int Op, CacheClient_t *Client)
+{
+   _MSG("Script_load_callback: Op=%d\n", Op);
+   if (Op) { /* EOF */
+/*Are we really get javascript ? Maybe some thing below.*/
+/*
+
+

400 Bad Request


+Your request has bad syntax or is inherently impossible to satisfy.
+

+thttpd/2.20c 21nov01
+
+*/
+      DilloHtmlScript *s = (DilloHtmlScript *)Client->CbData;
+      s->Script((const char *)Client->Buf);
+/*
+      printf("Load %s complete\n", a_Url_str(Client->Url));
+      printf("**************************************************\n");
+      printf("%s\n", Client->Buf);
+      printf("**************************************************\n");
+*/
+   }
+}
+
+DilloHtmlScript::DilloHtmlScript(DilloHtml *_html, DilloHtmlScriptType _type, const DilloUrl *_src, const char *_script)
+: html(_html), type(_type), script(NULL)
+{
+  //src = (_src) ? dStrdup(_src) : NULL;
+  src = a_Url_dup(_src);
+  if(_script)
+    Script(_script);
+  else {
+      DilloWeb *Web;
+      int ClientKey;
+      /* Fill a Web structure for the cache query */
+      Web = a_Web_new(src);
+      Web->bw = html->bw;
+      if ((ClientKey = a_Capi_open_url(Web, Script_load_callback, this)) != 0) {
+         a_Bw_add_client(html->bw, ClientKey, 0);
+         a_Bw_add_url(html->bw, src);
+      }
+  }
+}
+
+DilloHtmlScript::~DilloHtmlScript()
+{
+  a_Url_free(src);
+  if(script)
+    dFree(script);
+  if(input)
+    SEE_INPUT_CLOSE(input);
+}
+
+void DilloHtmlScript::Script(const char *_script)
+{
+  if(_script == NULL)
+    return;
+
+  script = dStrdup(_script);
+}
+
+void DilloHtmlScript::Input()
+{
+  input = SEE_input_utf8(interp, script);
+  if(src)
+    input->filename = SEE_intern_ascii(interp, a_Url_str(src));
+  else
+    input->filename = SEE_intern_ascii(interp, "");
+  run_input(input, NULL);
+}
+
+DilloHtmlScript *a_Html_script_new(DilloHtml *html, DilloHtmlScriptType type, const DilloUrl *src, const char *script)
+{
+  return new DilloHtmlScript(html, type, src, script);
+}
+
+/*
+*
+*/
+
+struct method {
+  const char *name;
+  void (*fn)(struct SEE_interpreter *, struct SEE_object *,
+    struct SEE_object *, int, struct SEE_value **,
+    struct SEE_value *);
+  int expected_args;
+};
+/*
+static void
+add_methods(interpreter, object, methods)
+  struct SEE_interpreter *interpreter;
+  struct SEE_object *object;
+  const struct method *methods;
+*/
+static void
+add_methods(struct SEE_interpreter *interpreter,
+  struct SEE_object* object,
+  const struct method *methods)
+{
+  unsigned int i;
+
+  for (i = 0; methods[i].name; i++)
+    SEE_CFUNCTION_PUTA(interpreter, object,
+        methods[i].name, methods[i].fn,
+        methods[i].expected_args, 0);
+}
+
+/*
+ * A write function that prints its output to stdout.
+ * No newline is appended.
+ */
+static void
+document_write(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  struct SEE_value v;
+
+  if (argc) {
+    SEE_ToString(interp, argv[0], &v);
+    SEE_string_fputs(v.u.string, stdout);
+    fflush(stdout);
+  }
+  SEE_SET_UNDEFINED(res);
+}
+
+/*
+ * A function that gets forms object by name.
+*/
+static void
+document_getElementById(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  struct SEE_value v, s;
+
+  if(thisobj && argc) {
+    SEE_ToString(interp, argv[0], &s);
+    SEE_OBJECT_GET(interp, thisobj, SEE_intern(interp, s.u.string), &v);
+    if (SEE_VALUE_GET_TYPE(&v) == SEE_OBJECT) {
+      SEE_SET_OBJECT(res, v.u.object);  /*Object already created, just return it.*/
+      return;
+    }
+  }
+
+  SEE_SET_UNDEFINED(res);
+}
+
+/*
+* Form submit
+*/
+static void
+form_submit(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  SEE_SET_UNDEFINED(res);
+}
+
+/*
+* Form reset
+*/
+static void
+form_reset(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  DilloHtmlInput *i = (DilloHtmlInput *)thisobj->host_data;
+  i->reset();
+
+  SEE_SET_UNDEFINED(res);
+}
+
+/*
+* Input focus
+*/
+static void
+input_focus(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  SEE_SET_UNDEFINED(res);
+}
+
+static void
+global_alert(struct SEE_interpreter *interpreter,
+  struct SEE_object *self,
+  struct SEE_object *thisobj,
+  int argc,
+  struct SEE_value **argv,
+  struct SEE_value *res)
+{
+  SEE_SET_UNDEFINED(res);
+}
+
+/*
+*
+*/
+#if WITH_BOEHM_GC
+# include
+#endif
+
+void a_Dom_setup(DilloHtml *html)
+{
+  static int interp_initialised = 0;
+  static struct SEE_interpreter i;
+
+  #if WITH_BOEHM_GC
+    GC_INIT();
+  #endif
+
+#define INIT_INTERP_ONCE do {       \
+  if (!interp_initialised) {      \
+      SEE_interpreter_init(&i);    \
+      interp_initialised = 1;     \
+  }           \
+  } while (0)
+
+  INIT_INTERP_ONCE;
+
+  interp = &i;
+  
+  SEE_CFUNCTION_PUTA(interp, interp->Global, "alert", global_alert, 1, 0); /*form.length*/
+
+  struct SEE_object *document, *forms;
+  struct SEE_value v;
+
+  document = SEE_Object_new(interp);
+  document->host_data = html;
+  SEE_SET_OBJECT(&v, document);
+  SEE_OBJECT_PUTA(interp, interp->Global, "document", &v, 0);
+
+  static const struct method document_methods[] = {
+    { "write", document_write,  1 },
+    { "getElementById", document_getElementById, 1  },
+    {0}
+  };
+
+  add_methods(interp, document, document_methods);
+
+  /**/
+
+  forms = SEE_Object_new(interp);
+  forms->host_data = html->forms;
+  SEE_SET_OBJECT(&v, forms);
+  SEE_OBJECT_PUTA(interp, document, "forms", &v, 0);
+/*forms.length -> number of forms in a document */
+  SEE_SET_NUMBER(&v, html->forms->size());
+  SEE_OBJECT_PUTA(interp, forms, "length", &v, 0);
+
+
+  if(html->forms) {
+/*Create object according to form name*/
+    int c;
+    for(c=0;c forms->size();c++)  {
+      DilloHtmlForm* f = html->forms->get(c);
+      if(!f || !f->name)  /*Object MUST exist and have a name*/
+        continue;
+/**/
+      struct SEE_object *form = SEE_Object_new(interp);
+      form->host_data = f;
+      SEE_SET_OBJECT(&v, form);
+      SEE_OBJECT_PUTA(interp, document, f->name, &v, 0);
+/*form.length*/
+      SEE_SET_NUMBER(&v, f->inputs->size());
+      SEE_OBJECT_PUTA(interp, form, "length", &v, 0);
+
+/*form.method*/    
+      switch(f->method) {
+        case DILLO_HTML_METHOD_UNKNOWN: SEE_SET_STRING(&v, SEE_string_sprintf(interp, ""));
+          break;
+        case DILLO_HTML_METHOD_GET: SEE_SET_STRING(&v, SEE_string_sprintf(interp, "get"));
+          break;
+        case DILLO_HTML_METHOD_POST:  SEE_SET_STRING(&v, SEE_string_sprintf(interp, "post"));
+          break;
+      }
+      SEE_OBJECT_PUTA(interp, form, "method", &v, 0);
+/*form.submit()*/      
+      SEE_CFUNCTION_PUTA(interp, form, "submit", form_submit, 0, 0); /*form.submit*/
+/*form.reset()*/      
+      SEE_CFUNCTION_PUTA(interp, form, "reset", form_reset, 0, 0); /*form.reset*/
+
+/*Create object according to input name*/
+      lout::misc::SimpleVector *inputs = f->inputs;
+      if(inputs)  {
+        int cc;
+        for(cc=0;cc size();cc++) {
+          DilloHtmlInput *i = inputs->get(cc);
+          if(!i || !i->name)  /*Object MUST exist and have a name*/
+            continue;
+          struct SEE_object *inp = SEE_Object_new(interp);
+          inp->host_data = i;
+          SEE_SET_OBJECT(&v, inp);
+          SEE_OBJECT_PUTA(interp, form, i->name, &v, 0);
+
+/*input.value*/          
+          switch (i->type) {
+            case DILLO_HTML_INPUT_TEXT:
+            case DILLO_HTML_INPUT_PASSWORD:
+            case DILLO_HTML_INPUT_INDEX:
+            case DILLO_HTML_INPUT_HIDDEN: {
+              EntryResource *entryres = (EntryResource*)i->embed->getResource();
+              SEE_SET_STRING(&v, SEE_string_sprintf(interp, "%s", entryres->getText()));
+            } break;
+            default:
+              SEE_SET_STRING(&v, SEE_string_sprintf(interp, ""));
+              break;
+          }
+          SEE_OBJECT_PUTA(interp, inp, "value", &v, 0);
+/*input.focus()*/
+          SEE_CFUNCTION_PUTA(interp, inp, "focus", input_focus, 0, 0);
+        }
+      }
+    }
+  }
+}
+
+/*
+*
+*/
+
+void *a_Html_script_run(DilloHtml *html, const char *script)
+{  
+  a_Dom_setup(html);
+
+  int i;
+  for(i=0;i scripts->size();i++)  {
+    DilloHtmlScript *s = html->scripts->get(i);
+    s->Input();
+  }
+
+  static struct SEE_value res, rstr;
+  struct SEE_input *input;
+  SEE_string *r;
+
+printf("Run : %s\n", script);
+  input = SEE_input_utf8(interp, script);
+  if (run_input(input, &res)) {
+    printf(" = ");
+    SEE_PrintValue(interp, &res, stdout);
+    printf("\n");
+  }
+
+  SEE_INPUT_CLOSE(input);
+
+  switch(SEE_VALUE_GET_TYPE(&res))  {
+    case SEE_UNDEFINED:
+    case SEE_NULL:
+    case SEE_OBJECT:
+      return 0;
+    case SEE_BOOLEAN:
+      return (void *)res.u.boolean;
+    case SEE_NUMBER:
+      //return (void *)res.u.number;
+    case SEE_STRING:
+      SEE_ToString(interp, &res, &rstr);
+      r = rstr.u.string;
+      break;
+    default:
+      return 0;
+  }
+  
+  return r->data;
+}
+
diff -r 468e535f1435 src/form.hh
--- a/src/form.hh    Wed May 13 13:31:37 2009 -0400
+++ b/src/form.hh    Thu May 14 23:48:02 2009 +0800
@@ -31,6 +31,7 @@ class DilloHtml;
  */
 
 DilloHtmlForm *a_Html_form_new(DilloHtml *html,
+                               char *name,
                                DilloHtmlMethod method,
                                const DilloUrl *action,
                                DilloHtmlEnc enc,
@@ -59,4 +60,20 @@ void Html_tag_open_button(DilloHtml *htm
 void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize);
 void Html_tag_close_button(DilloHtml *html, int TagIdx);
 
+/*
+* Script
+*/
+
+void a_Dom_setup(DilloHtml *html);
+
+typedef enum {
+   DILLO_HTML_JAVASCRIPT,
+   DILLO_HTML_VBSCRIPT
+} DilloHtmlScriptType;
+
+class DilloHtmlScript;
+
+DilloHtmlScript *a_Html_script_new(DilloHtml *html, DilloHtmlScriptType type, const DilloUrl *src, const char *script);
+void *a_Html_script_run(DilloHtml *html, const char *script);
+
 #endif /* __FORM_HH__ */
diff -r 468e535f1435 src/html.cc
--- a/src/html.cc    Wed May 13 13:31:37 2009 -0400
+++ b/src/html.cc    Thu May 14 23:48:02 2009 +0800
@@ -40,6 +40,8 @@
 #include "html_common.hh"
 #include "form.hh"
 #include "table.hh"
+
+#include "dom.hh"
 
 #include "dw/textblock.hh"
 #include "dw/bullet.hh"
@@ -472,6 +474,7 @@ DilloHtml::DilloHtml(BrowserWindow *p_bw
    inputs_outside_form = new misc::SimpleVector (1);
    links = new misc::SimpleVector (64);
    images = new misc::SimpleVector (16);
+   scripts = new misc::SimpleVector   (1);
    //a_Dw_image_map_list_init(&maps);
 
    /* Initialize the main widget */
@@ -635,18 +638,28 @@ void DilloHtml::finishParsing(int Client
 /*
  * Allocate and insert form information.
  */
-int DilloHtml::formNew(DilloHtmlMethod method, const DilloUrl *action,
+int DilloHtml::formNew(char *name, DilloHtmlMethod method, const DilloUrl *action,
                        DilloHtmlEnc enc, const char *charset)
 {
    // avoid data loss on repush after CSS stylesheets have been loaded
    bool enabled = bw->NumPendingStyleSheets == 0;
-   DilloHtmlForm *form = a_Html_form_new (this, method, action,
+   DilloHtmlForm *form = a_Html_form_new (this, name, method, action,
                                           enc, charset, enabled);
    int nf = forms->size ();
    forms->increase ();
    forms->set (nf, form);
    _MSG("Html formNew: action=%s nform=%d\n", action, nf);
    return forms->size();
+}
+
+int DilloHtml::scriptNew(DilloHtmlScriptType type, const DilloUrl *src, const char *script)
+{
+   DilloHtmlScript *s = a_Html_script_new(this, type, src, script);
+   int ns = scripts->size ();
+   scripts->increase ();
+   scripts->set (ns, s);
+   _MSG("Html scriptNew: src=%s nform=%d\n", a_Url_str(src), ns);
+   return scripts->size();
 }
 
 /*
@@ -1624,6 +1637,20 @@ static void Html_tag_close_title(DilloHt
  */
 static void Html_tag_open_script(DilloHtml *html, const char *tag, int tagsize)
 {
+   const char *attrbuf;
+   attrbuf = a_Html_get_attr(html, tag, tagsize, "language");
+   if(attrbuf) {
+   if(dStristr(attrbuf, "javascript"))  {
+      //printf("JavaScript\n");
+
+      DilloUrl *url;
+      if (!(attrbuf = a_Html_get_attr(html, tag, tagsize, "src")) ||
+       !(url = a_Html_url_new(html, attrbuf, NULL, 0)))
+         goto script_done;
+
+      html->scriptNew(DILLO_HTML_JAVASCRIPT, url, 0);
+   }
+   }
+
+script_done:
    a_Html_stash_init(html);
    S_TOP(html)->parse_mode = DILLO_HTML_PARSE_MODE_VERBATIM;
 }
@@ -1633,7 +1660,10 @@ static void Html_tag_open_script(DilloHt
  */
 static void Html_tag_close_script(DilloHtml *html, int TagIdx)
 {
+   //printf("html->Stash->str = \n%s\n", html->Stash->str);
    /* eventually the stash will be sent to an interpreter for parsing */
+   if(html->Stash->str && html->Stash->str != "")
+      html->scriptNew(DILLO_HTML_JAVASCRIPT, 0, html->Stash->str);
 }
 
 /*
@@ -3425,7 +3455,7 @@ static void Html_process_tag(DilloHtml *
    }
 
    /* Handle HTML, HEAD and BODY. Elements with optional open and close */
-   if (!(html->InFlags & IN_BODY) /* && parsing HTML */)
+   if (!(html->InFlags & IN_BODY) && (ni != 54)/* && parsing HTML */)
       Html_test_section(html, ni, IsCloseTag);
 
    /* Tag processing */
diff -r 468e535f1435 src/html_common.hh
--- a/src/html_common.hh    Wed May 13 13:31:37 2009 -0400
+++ b/src/html_common.hh    Thu May 14 23:48:02 2009 +0800
@@ -14,6 +14,8 @@
 #include "form.hh"
 
 #include "styleengine.hh"
+
+#include "dom.hh"
 
 /*
  * Macros
@@ -196,6 +198,7 @@ public:  //BUG: for now everything is pu
    lout::misc::SimpleVector *inputs_outside_form;
    lout::misc::SimpleVector *links;
    lout::misc::SimpleVector *images;
+   lout::misc::SimpleVector *scripts;
    dw::ImageMapsList maps;
 
 private:
@@ -210,8 +213,9 @@ public:
    void write(char *Buf, int BufSize, int Eof);
    int getCurTagLineNumber();
    void finishParsing(int ClientKey);
-   int formNew(DilloHtmlMethod method, const DilloUrl *action,
+   int formNew(char *name, DilloHtmlMethod method, const DilloUrl *action,
                DilloHtmlEnc enc, const char *charset);
+   int scriptNew(DilloHtmlScriptType type, const DilloUrl *src, const char *script);
    DilloHtmlForm *getCurrentForm ();
    bool_t unloadedImages();
    void loadImages (const DilloUrl *pattern);


沒有留言:

張貼留言