Check-in [5861340a25]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move towards the new javascript architecture. One js interpreter per frame, special wrapper objects to allow scripts in one interpreter to use the objects from another. (CVS 1267)
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:5861340a25fb11c50581becf13d5d2049bddae2d
User & Date: danielk1977 2008-02-15 18:23:37
Context
2008-02-15
18:54
Remove a few files that haven't been used for a while. (CVS 1268) check-in: 985e5d061f user: danielk1977 tags: trunk
18:23
Move towards the new javascript architecture. One js interpreter per frame, special wrapper objects to allow scripts in one interpreter to use the objects from another. (CVS 1267) check-in: 5861340a25 user: danielk1977 tags: trunk
2008-02-14
08:43
Do not draw to unmapped windows. (CVS 1266) check-in: 356765ca5b user: danielk1977 tags: trunk
Changes

Changes to COMPILE.txt.

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    JS_SHARED_LIB.

  Hints for compiling SEE:

    If Boehm GC is not in the various paths, need to set CFLAGS, LDFLAGS and
    LD_LIBRARY_PATH before running configure:

      INSTALL_PATH=/home/dan/javascript/install
      export CFLAGS="-I${INSTALL_PATH}/include/ -O2 -DNDEBUG"
      export LDFLAGS=-L${INSTALL_PATH}/lib/
      export LD_LIBRARY_PATH=${INSTALL_PATH}/lib/

    Then supply an installation path to configure:

      ../see-2.1.1206_snapshot/configure --prefix=${INSTALL_PATH}/







|







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    JS_SHARED_LIB.

  Hints for compiling SEE:

    If Boehm GC is not in the various paths, need to set CFLAGS, LDFLAGS and
    LD_LIBRARY_PATH before running configure:

      INSTALL_PATH=/home/dan/work/tkhtml/js/
      export CFLAGS="-I${INSTALL_PATH}/include/ -O2 -DNDEBUG"
      export LDFLAGS=-L${INSTALL_PATH}/lib/
      export LD_LIBRARY_PATH=${INSTALL_PATH}/lib/

    Then supply an installation path to configure:

      ../see-2.1.1206_snapshot/configure --prefix=${INSTALL_PATH}/

Changes to hv/hv3.tcl.

1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
....
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106















1107
1108
1109
1110
1111
1112
1113
....
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249

1250
1251
1252
1253
1254
1255
1256
....
1283
1284
1285
1286
1287
1288
1289

1290
1291
1292
1293
1294
1295
1296
....
1334
1335
1336
1337
1338
1339
1340
1341

1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
....
1938
1939
1940
1941
1942
1943
1944
1945

1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962

1963
1964
1965

1966
1967
1968
1969
1970
1971
1972
....
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
....
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
....
2185
2186
2187
2188
2189
2190
2191
2192
2193







2194

2195
2196
2197
2198
2199
2200
2201
....
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242

2243
2244
2245
2246
2247
2248
2249
2250

2251
2252
2253
2254
2255
2256
2257
          background-color: #d9d9d9; 
          background-color: white;
          padding: 5px;
          border: 1px solid;
          border-color: #828282 #ffffff #ffffff #828282;
        }
      </style>
    <h1>Plain Text File:</h1>
    <pre>
  }

  proc new {me args} {
    upvar #0 $me O
    set win $O(win)
	   
................................................................................
    set O(myMouseManager)     [mousemanager       %AUTO% $me]
    set O(myHyperlinkManager) [hyperlinkmanager   %AUTO% $me $O(myBase)]
    set O(mySelectionManager) [selectionmanager   %AUTO% $me]
    set O(myDynamicManager)   [dynamicmanager     %AUTO% $me]
    set O(myFormManager)      [::hv3::formmanager %AUTO% $me]
    set O(myFrameLog)         [framelog           %AUTO% $me]

    set O(-dom) ""
    set O(-storevisitedcmd) ""

    set O(myStorevisitedDone) 0
    set O(-historydoccmd) ""

    # The option to display images (default true).
    set O(-enableimages) 1
















    set O(-scrollbarpolicy) auto

    set O(-locationvar) ""
    set O(-downloadcmd) ""
    set O(-requestcmd) ""

................................................................................
    catch { $O(mySelectionManager) destroy }
    catch { $O(myDynamicManager)   destroy }
    catch { $O(myHyperlinkManager) destroy }
    catch { $O(myUri)              destroy }
    catch { $O(myFormManager)      destroy }
    catch { $O(myMouseManager)     destroy }
    catch { $O(myBase)             destroy }

    # Tell the DOM implementation that any Window object created for
    # this widget is no longer required.
    catch { $O(-dom) delete_window $me }


    # Cancel any refresh-event that may be pending.
    if {$O(myRefreshEventId) ne ""} {
      after cancel $O(myRefreshEventId)
      set O(myRefreshEventId) ""
    }

................................................................................
    upvar #0 $me O
    return [$O(myUri) get] 
  }

  # Return the referrer URI of the widget.
  #
  proc referrer {me} { 

    return $O(myReferrer) 
  }

  proc Forget {me handle} {
    upvar #0 $me O
    set idx [lsearch $O(myActiveHandles) $handle]
    set O(myActiveHandles) [lreplace $O(myActiveHandles) $idx $idx]
................................................................................
  proc MightBeComplete {me } {
    upvar #0 $me O
    if {[llength $O(myActiveHandles)] == 0} {
      event generate $O(win) <<Complete>>

      # There are no outstanding HTTP transactions. So fire
      # the DOM "onload" event.
      if {$O(-dom) ne "" && !$O(myOnloadFired)} {

        set bodynode [$O(myHtml) search body]
	# Workaround. Currently meta reload causes empty completion.
	# XXX: Check this again!
	if {[llength $bodynode]} {
	    $O(-dom) event load [lindex $bodynode 0]
	}
      }
      set O(myOnloadFired) 1
    }
  }

  proc onload_fired {me } { 
    upvar #0 $me O
    return $O(myOnloadFired) 
  }
................................................................................
    upvar #0 $me O
    set cmd [linsert [$me cget -targetcmd] end $node]
    [eval $cmd] Formcmd2 $method $uri $querytype $encdata
  }

  proc Formcmd2 {me method uri querytype encdata} {
    upvar #0 $me O
    # puts "Formcmd $method $uri $querytype $encdata"

    set full_uri [$me resolve_uri $uri]

    event generate $O(win) <<Goto>>

    set handle [::hv3::request %AUTO% -mimetype text/html]
    set O(myMimetype) ""
    set referer [$me uri get]
    $handle configure                                       \
        -incrscript [list $me documentcallback $handle $referer 1 0] \
        -finscript  [list $me documentcallback $handle $referer 1 1] \
        -requestheader [list Referer $referer]              \

    if {$method eq "post"} {
      $handle configure -uri $full_uri -postdata $encdata
      $handle configure -enctype $querytype
      $handle configure -cachecontrol normal
    } else {

      $handle configure -uri "${full_uri}?${encdata}"
      $handle configure -cachecontrol $O(myCacheControl)
    }

    $me makerequest $handle

    # Grab the keyboard focus for this widget. This is so that after
    # the form is submitted the arrow keys and PgUp/PgDown can be used
    # to scroll the main display.
    #
    focus [$me html]
................................................................................
  #     goto                N/A
  #     xview               $O(myHtml)
  #     yview               $O(myHtml)
  #     html                N/A
  #     hull                N/A
  #   

  proc dom {me } { 
    upvar #0 $me O
    if {$O(-dom) eq ""} { return ::hv3::ignore_script }
    return $O(-dom)
  }

  #--------------------------------------------------------------------
  # Load the URI specified as an argument into the main browser window.
  # This method has the following syntax:
  #
  #     $hv3 goto URI ?OPTIONS?
................................................................................
      }
    }

    # Special case. If this URI begins with "javascript:" (case independent),
    # pass it to the current running DOM implementation instead of loading
    # anything into the current browser.
    if {[string match -nocase javascript:* $uri]} {
      if {$O(-dom) ne ""} {
        $O(-dom) javascript $me [string range $uri 11 end]
      }
      return
    }

    set O(myCacheControl) $cachecontrol

    set current_uri [$O(myUri) get_no_fragment]
................................................................................
        $O(mySelectionManager) $O(myHyperlinkManager) \
    ] {
      if {$m ne ""} {$m reset}
    }
    $O(html) reset
    $O(myHtml) configure -scrollbarpolicy $O(-scrollbarpolicy)

    if {$O(-dom) ne ""} {
      $O(-dom) clear_window $me







    }

  }

  proc reset {me isSaveState} {
    upvar #0 $me O

    # Clear the "onload-event-fired" flag
    set O(myOnloadFired) 0
................................................................................
    if {$O(-enableimages)} {
      $O(myHtml) configure -imagecmd [list $me Imagecmd]
    } else {
      $O(myHtml) configure -imagecmd ""
    }
  }

  proc configure-dom {me} {
    upvar #0 $me O


    $O(myMouseManager) configure -dom $O(-dom)
    if {$O(-dom) ne ""} {
      $O(myHtml) handler script script   [list $O(-dom) script $me]
      $O(myHtml) handler script noscript [list $O(-dom) noscript $me]
      $O(-dom) make_window $me
    } else {
      $O(myHtml) handler script script   ::hv3::ignore_script
      $O(myHtml) handler script noscript {}

    }
  }

  proc pending {me}  {
    upvar #0 $me O
    return [llength $O(myActiveHandles)]
  }







<







 







<







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
>







 







>







 







|
>




|


<







 







|
>
|












|



>
|


>







 







|

|
|







 







|
|







 







|
|
>
>
>
>
>
>
>

>







 







|

<
>
|
|
<
<
<
<


>







1066
1067
1068
1069
1070
1071
1072

1073
1074
1075
1076
1077
1078
1079
....
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
....
1252
1253
1254
1255
1256
1257
1258




1259
1260
1261
1262
1263
1264
1265
1266
....
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363
1364
1365
1366
1367
....
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
....
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
....
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
....
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
....
2255
2256
2257
2258
2259
2260
2261
2262
2263

2264
2265
2266




2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
          background-color: #d9d9d9; 
          background-color: white;
          padding: 5px;
          border: 1px solid;
          border-color: #828282 #ffffff #ffffff #828282;
        }
      </style>

    <pre>
  }

  proc new {me args} {
    upvar #0 $me O
    set win $O(win)
	   
................................................................................
    set O(myMouseManager)     [mousemanager       %AUTO% $me]
    set O(myHyperlinkManager) [hyperlinkmanager   %AUTO% $me $O(myBase)]
    set O(mySelectionManager) [selectionmanager   %AUTO% $me]
    set O(myDynamicManager)   [dynamicmanager     %AUTO% $me]
    set O(myFormManager)      [::hv3::formmanager %AUTO% $me]
    set O(myFrameLog)         [framelog           %AUTO% $me]


    set O(-storevisitedcmd) ""

    set O(myStorevisitedDone) 0
    set O(-historydoccmd) ""

    # The option to display images (default true).
    set O(-enableimages) 1

    # The option to execute javascript (default false). 
    #
    # When javascript is enabled, the O(myDom) variable is set to the name of
    # an object of type [::hv3::dom]. When it is not enabled, O(myDom) is
    # an empty string.
    #
    # When the -enablejavascript option is changed from true to false,
    # the O(myDom) object is deleted (and O(myDom) set to the empty 
    # string). But the dom object is not created immediately when 
    # -enablejavascript is changed from false to true. Instead, we
    # wait until the next time the hv3 widget is reset.
    #
    set O(-enablejavascript) 0
    set O(myDom) ""

    set O(-scrollbarpolicy) auto

    set O(-locationvar) ""
    set O(-downloadcmd) ""
    set O(-requestcmd) ""

................................................................................
    catch { $O(mySelectionManager) destroy }
    catch { $O(myDynamicManager)   destroy }
    catch { $O(myHyperlinkManager) destroy }
    catch { $O(myUri)              destroy }
    catch { $O(myFormManager)      destroy }
    catch { $O(myMouseManager)     destroy }
    catch { $O(myBase)             destroy }




    catch { $O(myDom)              destroy }

    # Cancel any refresh-event that may be pending.
    if {$O(myRefreshEventId) ne ""} {
      after cancel $O(myRefreshEventId)
      set O(myRefreshEventId) ""
    }

................................................................................
    upvar #0 $me O
    return [$O(myUri) get] 
  }

  # Return the referrer URI of the widget.
  #
  proc referrer {me} { 
    upvar #0 $me O
    return $O(myReferrer) 
  }

  proc Forget {me handle} {
    upvar #0 $me O
    set idx [lsearch $O(myActiveHandles) $handle]
    set O(myActiveHandles) [lreplace $O(myActiveHandles) $idx $idx]
................................................................................
  proc MightBeComplete {me } {
    upvar #0 $me O
    if {[llength $O(myActiveHandles)] == 0} {
      event generate $O(win) <<Complete>>

      # There are no outstanding HTTP transactions. So fire
      # the DOM "onload" event.
      if {$O(myDom) ne "" && !$O(myOnloadFired)} {
        set O(myOnloadFired) 1
        set bodynode [$O(myHtml) search body]
	# Workaround. Currently meta reload causes empty completion.
	# XXX: Check this again!
	if {[llength $bodynode]} {
          $O(myDom) event load [lindex $bodynode 0]
	}
      }

    }
  }

  proc onload_fired {me } { 
    upvar #0 $me O
    return $O(myOnloadFired) 
  }
................................................................................
    upvar #0 $me O
    set cmd [linsert [$me cget -targetcmd] end $node]
    [eval $cmd] Formcmd2 $method $uri $querytype $encdata
  }

  proc Formcmd2 {me method uri querytype encdata} {
    upvar #0 $me O
    puts "Formcmd $method $uri $querytype $encdata"

    set uri_obj [::tkhtml::uri [$me resolve_uri $uri]]

    event generate $O(win) <<Goto>>

    set handle [::hv3::request %AUTO% -mimetype text/html]
    set O(myMimetype) ""
    set referer [$me uri get]
    $handle configure                                       \
        -incrscript [list $me documentcallback $handle $referer 1 0] \
        -finscript  [list $me documentcallback $handle $referer 1 1] \
        -requestheader [list Referer $referer]              \

    if {$method eq "post"} {
      $handle configure -uri [$uri_obj get] -postdata $encdata
      $handle configure -enctype $querytype
      $handle configure -cachecontrol normal
    } else {
      $uri_obj load "?$encdata"
      $handle configure -uri [$uri_obj get]
      $handle configure -cachecontrol $O(myCacheControl)
    }
    $uri_obj destroy
    $me makerequest $handle

    # Grab the keyboard focus for this widget. This is so that after
    # the form is submitted the arrow keys and PgUp/PgDown can be used
    # to scroll the main display.
    #
    focus [$me html]
................................................................................
  #     goto                N/A
  #     xview               $O(myHtml)
  #     yview               $O(myHtml)
  #     html                N/A
  #     hull                N/A
  #   

  proc dom {me} { 
    upvar #0 $me O
    if {$O(myDom) eq ""} { return ::hv3::ignore_script }
    return $O(myDom)
  }

  #--------------------------------------------------------------------
  # Load the URI specified as an argument into the main browser window.
  # This method has the following syntax:
  #
  #     $hv3 goto URI ?OPTIONS?
................................................................................
      }
    }

    # Special case. If this URI begins with "javascript:" (case independent),
    # pass it to the current running DOM implementation instead of loading
    # anything into the current browser.
    if {[string match -nocase javascript:* $uri]} {
      if {$O(myDom) ne ""} {
        $O(myDom) javascript [string range $uri 11 end]
      }
      return
    }

    set O(myCacheControl) $cachecontrol

    set current_uri [$O(myUri) get_no_fragment]
................................................................................
        $O(mySelectionManager) $O(myHyperlinkManager) \
    ] {
      if {$m ne ""} {$m reset}
    }
    $O(html) reset
    $O(myHtml) configure -scrollbarpolicy $O(-scrollbarpolicy)

    catch {$O(myDom) destroy}
    if {$O(-enablejavascript)} {
      set O(myDom) [::hv3::dom %AUTO% $me]
      $O(myHtml) handler script script   [list $O(myDom) script]
      $O(myHtml) handler script noscript ::hv3::ignore_script
    } else {
      set O(myDom) ""
      $O(myHtml) handler script script   ::hv3::ignore_script
      $O(myHtml) handler script noscript {}
    }
    $O(myMouseManager) configure -dom $O(myDom)
  }

  proc reset {me isSaveState} {
    upvar #0 $me O

    # Clear the "onload-event-fired" flag
    set O(myOnloadFired) 0
................................................................................
    if {$O(-enableimages)} {
      $O(myHtml) configure -imagecmd [list $me Imagecmd]
    } else {
      $O(myHtml) configure -imagecmd ""
    }
  }

  proc configure-enablejavascript {me} {
    upvar #0 $me O

    if {!$O(-enablejavascript)} {
      catch {$O(myDom) destroy}
      set O(myDom) ""




      $O(myHtml) handler script script   ::hv3::ignore_script
      $O(myHtml) handler script noscript {}
      $O(myMouseManager) configure -dom ""
    }
  }

  proc pending {me}  {
    upvar #0 $me O
    return [llength $O(myActiveHandles)]
  }

Changes to hv/hv3_browser.tcl.

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
137
138
139
140
141
142
143



144
145
146
147
148
149
150

151
152
153


154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
526
527
528
529
530
531
532

533
534
535
536
537
538
539
...
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
...
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
...
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
...
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
    # If "Copy Link Location" has been selected, store the selected text
    # (a URI) in set $O(myCopiedLinkLocation).
    set O(myCopiedLinkLocation) ""
 
    #set O(myHv3)      [::hv3::hv3 $O(win).hv3]
    #pack $O(myHv3) -expand true -fill both
    set O(myHv3) $O(hull)
    $O(myHv3) configure -frame me

    ::hv3::the_visited_db init $O(myHv3)

    catch {$O(myHv3) configure -fonttable $::hv3::fontsize_table}

    # Create bindings for motion, right-click and middle-click.
    $O(myHv3) Subscribe motion [list $me motion]
................................................................................
    catch {$me ConfigureName -name ""}
    # Remove this object from the $theFrames list.
    catch {$O(myBrowser) del_frame $O(win)} msg
    catch {::destroy $O(win).hyperlinkmenu}
  }

  proc configure-name {me} {



    upvar #0 $me O

    # This method is called when the "name" of attribute of this
    # frame is modified. If javascript is enabled we have to update
    # the properties on the parent window object (if any).
    set dom [$me cget -dom]
    if {$dom ne "" && [$dom cget -enable]} {

      set parent [$me parent_frame]
      if {$parent ne ""} {
        set parent_window [list ::hv3::DOM::Window $dom [$parent hv3]]


        set this_win [list ::hv3::DOM::Window $dom $O(myHv3)]
        if {$O(oldname) ne ""} {
          $dom set_object_property $parent_window $O(oldname) undefined
        }
        if {$O(-name) ne ""} {
          set val [list object $this_win]
          $dom set_object_property $parent_window $O(-name) $val
        }
      }
    }

    set O(oldname) $O(-name)
  }

................................................................................
        }
      }
    }

    return $widget
  }

  proc parent_frame {me } {
    upvar #0 $me O
    set frames [$O(myBrowser) get_frames]
    set w [winfo parent $O(win)]
    while {$w ne "" && [lsearch $frames $w] < 0} {
      set w [winfo parent $w]
    }
    return $w
................................................................................
  }

  set DelegateOption(-forcefontmetrics) myHv3
  set DelegateOption(-fonttable)        myHv3
  set DelegateOption(-fontscale)        myHv3
  set DelegateOption(-zoom)             myHv3
  set DelegateOption(-enableimages)     myHv3

  set DelegateOption(-dom)              myHv3
  set DelegateOption(-width)            myHv3
  set DelegateOption(-height)           myHv3
  set DelegateOption(-requestcmd)       myHv3
  set DelegateOption(-resetcmd)         myHv3
  set DelegateOption(-downloadcmd)      myHv3

................................................................................

    # Initialize the global database connection if it has not already
    # been initialized. TODO: Remove the global variable.
    ::hv3::dbinit

    set O(-stopbutton) ""
    set O(-unsafe) 0
    set O(-enablejavascript) 0

    # Variables passed to [$myProtocol configure -statusvar] and
    # the same option of $myMainFrame. Used to create the value for 
    # $myStatusVar.
    set O(myProtocolStatus) ""
    set O(myFrameStatus) ""

................................................................................
    set O(myStatusVar) ""
    set O(myLocationVar) ""

    # List of all ::hv3::browser_frame objects using this object as
    # their toplevel browser. 
    set O(myFrames) [list]

    set O(myDom) [::hv3::dom %AUTO% $me]

    # Create the protocol object.
    set O(myProtocol) [::hv3::protocol %AUTO%]

    # The main browser frame (always present).
    set O(myHistory) ""
    set O(myMainFrame) [::hv3::browser_frame $O(win).frame $me]
    #set O(myMainFrame) $O(hull)
................................................................................
    eval $me configure $args
  }

  proc destroy {me} {
    upvar #0 $me O
    if {$O(myProtocol) ne ""} { $O(myProtocol) destroy }
    if {$O(myHistory) ne ""}  { $O(myHistory) destroy }
    if {$O(myDom) ne ""}      { $O(myDom) destroy }
  }

  proc statusvar {me} { 
    return ${me}(myStatusVar)
  }
  proc titlevar {me args} { 
    upvar #0 $me O
................................................................................
    if {$O(myHistory) ne ""} {
      $O(myHistory) add_hv3 [$frame hv3]
    }
    set HTML [[$frame hv3] html]
    bind $HTML <1>               [list focus %W]
    bind $HTML <KeyPress-slash>  [list $me Find]
    bindtags $HTML [concat Hv3HotKeys $me [bindtags $HTML]]
    if {[$O(myDom) cget -enable]} {
      $frame configure -dom $O(myDom)
    }

    set cmd [list ::hv3::the_download_manager savehandle $O(myProtocol)]
    $frame configure -downloadcmd $cmd

    catch {$::hv3::G(config) configureframe $frame}
  }
  proc del_frame {me frame} {
................................................................................
  }

  proc reload {me } {
    upvar #0 $me O
    $O(myHistory) reload
  }

  proc configure-enablejavascript {me} {
    upvar #0 $me O
    $O(myDom) configure -enable $O(-enablejavascript)
    set dom ""
    if {$O(-enablejavascript)} { set dom $O(myDom) }
    foreach f $O(myFrames) {
      $f configure -dom $dom
    }
  }

  proc populate_history_menu {me args} {
    upvar #0 $me O
    eval $O(myHistory) populate_menu $args
  }
  proc populatehistorymenu {me args} {
    upvar #0 $me O
    eval $O(myHistory) populatehistorymenu $args







|







 







>
>
>





<
<
>
|
|
<
>
>
|

|

|
|
<







 







|







 







>







 







<







 







<
<







 







<







 







<
<
<







 







<
<
<
<
<
<
<
<
<
<







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151


152
153
154

155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
...
574
575
576
577
578
579
580

581
582
583
584
585
586
587
...
588
589
590
591
592
593
594


595
596
597
598
599
600
601
...
639
640
641
642
643
644
645

646
647
648
649
650
651
652
...
679
680
681
682
683
684
685



686
687
688
689
690
691
692
...
874
875
876
877
878
879
880










881
882
883
884
885
886
887
    # If "Copy Link Location" has been selected, store the selected text
    # (a URI) in set $O(myCopiedLinkLocation).
    set O(myCopiedLinkLocation) ""
 
    #set O(myHv3)      [::hv3::hv3 $O(win).hv3]
    #pack $O(myHv3) -expand true -fill both
    set O(myHv3) $O(hull)
    $O(myHv3) configure -frame $me

    ::hv3::the_visited_db init $O(myHv3)

    catch {$O(myHv3) configure -fonttable $::hv3::fontsize_table}

    # Create bindings for motion, right-click and middle-click.
    $O(myHv3) Subscribe motion [list $me motion]
................................................................................
    catch {$me ConfigureName -name ""}
    # Remove this object from the $theFrames list.
    catch {$O(myBrowser) del_frame $O(win)} msg
    catch {::destroy $O(win).hyperlinkmenu}
  }

  proc configure-name {me} {
    update_parent_dom $me [[$me hv3 dom] see] 
  }
  proc update_parent_dom {me my_see} {
    upvar #0 $me O

    # This method is called when the "name" of attribute of this
    # frame is modified. If javascript is enabled we have to update
    # the properties on the parent window object (if any).



    set parent [$me parent_frame]
    if {$parent ne ""} {

      set parent_see [[$parent hv3 dom] see] 

      if {$parent_see ne ""} { 
        if {$O(oldname) ne ""} {
          $parent_see global $O(oldname) undefined
        }
        if {$my_see ne ""} {
          $parent_see global $O(-name) [list bridge $my_see]

        }
      }
    }

    set O(oldname) $O(-name)
  }

................................................................................
        }
      }
    }

    return $widget
  }

  proc parent_frame {me} {
    upvar #0 $me O
    set frames [$O(myBrowser) get_frames]
    set w [winfo parent $O(win)]
    while {$w ne "" && [lsearch $frames $w] < 0} {
      set w [winfo parent $w]
    }
    return $w
................................................................................
  }

  set DelegateOption(-forcefontmetrics) myHv3
  set DelegateOption(-fonttable)        myHv3
  set DelegateOption(-fontscale)        myHv3
  set DelegateOption(-zoom)             myHv3
  set DelegateOption(-enableimages)     myHv3
  set DelegateOption(-enablejavascript) myHv3
  set DelegateOption(-dom)              myHv3
  set DelegateOption(-width)            myHv3
  set DelegateOption(-height)           myHv3
  set DelegateOption(-requestcmd)       myHv3
  set DelegateOption(-resetcmd)         myHv3
  set DelegateOption(-downloadcmd)      myHv3

................................................................................

    # Initialize the global database connection if it has not already
    # been initialized. TODO: Remove the global variable.
    ::hv3::dbinit

    set O(-stopbutton) ""
    set O(-unsafe) 0


    # Variables passed to [$myProtocol configure -statusvar] and
    # the same option of $myMainFrame. Used to create the value for 
    # $myStatusVar.
    set O(myProtocolStatus) ""
    set O(myFrameStatus) ""

................................................................................
    set O(myStatusVar) ""
    set O(myLocationVar) ""

    # List of all ::hv3::browser_frame objects using this object as
    # their toplevel browser. 
    set O(myFrames) [list]



    # Create the protocol object.
    set O(myProtocol) [::hv3::protocol %AUTO%]

    # The main browser frame (always present).
    set O(myHistory) ""
    set O(myMainFrame) [::hv3::browser_frame $O(win).frame $me]
    #set O(myMainFrame) $O(hull)
................................................................................
    eval $me configure $args
  }

  proc destroy {me} {
    upvar #0 $me O
    if {$O(myProtocol) ne ""} { $O(myProtocol) destroy }
    if {$O(myHistory) ne ""}  { $O(myHistory) destroy }

  }

  proc statusvar {me} { 
    return ${me}(myStatusVar)
  }
  proc titlevar {me args} { 
    upvar #0 $me O
................................................................................
    if {$O(myHistory) ne ""} {
      $O(myHistory) add_hv3 [$frame hv3]
    }
    set HTML [[$frame hv3] html]
    bind $HTML <1>               [list focus %W]
    bind $HTML <KeyPress-slash>  [list $me Find]
    bindtags $HTML [concat Hv3HotKeys $me [bindtags $HTML]]




    set cmd [list ::hv3::the_download_manager savehandle $O(myProtocol)]
    $frame configure -downloadcmd $cmd

    catch {$::hv3::G(config) configureframe $frame}
  }
  proc del_frame {me frame} {
................................................................................
  }

  proc reload {me } {
    upvar #0 $me O
    $O(myHistory) reload
  }











  proc populate_history_menu {me args} {
    upvar #0 $me O
    eval $O(myHistory) populate_menu $args
  }
  proc populatehistorymenu {me args} {
    upvar #0 $me O
    eval $O(myHistory) populatehistorymenu $args

Changes to hv/hv3_debug.tcl.

1
2
3
4
5
6
7
8
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
147
148
149
150
151
152
153
154
155
156



157

158
159
160
161
162
163
164
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
...
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
...
546
547
548
549
550
551
552
























553
554
555
556
557
558
559
namespace eval hv3 { set {version($Id: hv3_debug.tcl,v 1.15 2008/02/09 18:14:20 danielk1977 Exp $)} 1 }

namespace eval ::hv3 {
  ::snit::widget console {

    # Entry field for typing commands (entry widget):
    variable myEntryField 

................................................................................
      set b [frame ${win}.b]
      ::hv3::button ${b}.viewindex         \
          -text "Application Index"        \
          -command [list $self Display index ""]
      set myLabel [::hv3::label ${b}.label -anchor w]
      pack ${b}.viewindex -side left

      ::hv3::button ${b}.reorient -text Reorient -command [list $self Reorient]
      ::hv3::button ${b}.increasefont -text "+" -command [list $self font +2]
      ::hv3::button ${b}.decreasefont -text "-" -command [list $self font -2]
      pack ${b}.reorient -side right
      pack ${b}.increasefont -side right
      pack ${b}.decreasefont -side right

      pack ${b}.label -side left -fill x
................................................................................
        ${win}.b.decreasefont configure -state disabled
      } else {
        ${win}.b.decreasefont configure -state normal
      }
    }

    method Reorient {} {
      switch -- [${win}.pan cget -orient] {
        vertical   {${win}.pan configure -orient horizontal}
        horizontal {${win}.pan configure -orient vertical}



      }

    }


    # This method is called to evaluate a command typed into $myEntryField.
    #
    method Evaluate {} {
      set cmd [$myEntryField get]
................................................................................
        Javascript {
          set isEnabled [gui_current cget -enablejavascript]
          $myOutputWindow insert end "> $cmd\n" javascript
          if {!$isEnabled} {
            $myOutputWindow insert end "    Javascript is not enabled\n" error
          } else {
            set dom [[gui_current hv3] dom]
            set result [$dom javascript "" $cmd]
            set result [string map {"\n" "\n    "} $result]
            if {[lindex $result 0] eq "JS_ERROR"} {
              $myOutputWindow insert end "    $result\n" error
            } else {
              $myOutputWindow insert end "    $result\n"
            }
          }
................................................................................
      $myCodeViewer tag add wheat "$iLine.0" "$iLine.0 lineend"
    }
    method DisplayCssError {pageid iLine} {
      $self Display css $pageid
      $myCodeViewer yview -pickplace "$iLine.0"
    }

    proc getlogscript {dom name} {

      foreach logscript [$dom GetLog] {
        if {[$logscript cget -name] eq $name} {return $logscript}
      }
      return ""
    }

    method Errors {page pageid} {
................................................................................
          $myOutputWindow insert end "Error Message: \"[lindex $r 1]\"\n"
          if {[lindex $r 2] ne ""} {
              $myOutputWindow insert end "    "
              $myOutputWindow insert end "[lindex $r 2]\n"
          }

          foreach {zFile iLine zType zName} [lrange $r 3 end] {
            set target [getlogscript $dom $zFile]
            if {$target ne ""} {
              $myOutputWindow insert end "    "
              set cmd [list $self DisplayJavascriptError $idx $target $iLine]
              $self OutputWindowLink "Line $iLine, [$target cget -heading]" $cmd
              if {$zType ne "" || $zName ne ""} {
                $myOutputWindow insert end "  ($zType $zName)"
              }
................................................................................
	    {To browse the document source code, select a different option}
            {from the "Debug->Application Source Logging" menu and reload}
            {the document.}
        }]
        return
      }
      $self DisplayResources $top 2

      # Links for each loaded javascript file.
      #
      set dom [[gui_current hv3] dom]
      set ii 0
      foreach logscript [$dom GetLog] {
        if {[$logscript cget -isevent]} continue
        incr ii
        set cmd [list $self Display javascript [list $ii $logscript]]
        $myCodeViewer insert end "$ii. Javascript: [$logscript cget -heading]  "
        if {[$logscript cget -rc]} {
          set tag [$self CreateCodeViewerLink "(Failed)" [
              list $self Errors javascript [list $ii $dom $logscript]
          ]]
          $myCodeViewer tag configure $tag -foreground red
          $myCodeViewer insert end "  "
        } else {
          $myCodeViewer insert end "(Ok)  "
        }
        $self CreateCodeViewerLink "View Source" $cmd
        set nLine [llength [split [$logscript cget -script] "\n"]]
        $myCodeViewer insert end " ($nLine lines)\n"
      }
    }

    method DisplayResources {frame iIndent} {
      set hv3 [$frame hv3]

      set zIndent [string repeat " " $iIndent]
      set uri [$hv3 uri get]
................................................................................
            $myCodeViewer tag configure $t -foreground red
            $myCodeViewer insert end "  "
        }
        set cmd [list $self Display css [list $frame $id]]
        $self CreateCodeViewerLink "View Source" $cmd
        $myCodeViewer insert end "\n"
      }

























      $myCodeViewer insert end "\n"
      foreach child [$frame child_frames] {
        $self DisplayResources $child [expr {$iIndent+4}]
      }
    }
  }
|







 







|







 







|
|
|
>
>
>

>







 







|







 







|
>







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
..
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
492
493
494
495
496
497
498























499
500
501
502
503
504
505
...
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
namespace eval hv3 { set {version($Id: hv3_debug.tcl,v 1.16 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

namespace eval ::hv3 {
  ::snit::widget console {

    # Entry field for typing commands (entry widget):
    variable myEntryField 

................................................................................
      set b [frame ${win}.b]
      ::hv3::button ${b}.viewindex         \
          -text "Application Index"        \
          -command [list $self Display index ""]
      set myLabel [::hv3::label ${b}.label -anchor w]
      pack ${b}.viewindex -side left

      ::hv3::button ${b}.reorient -text Resize -command [list $self Reorient]
      ::hv3::button ${b}.increasefont -text "+" -command [list $self font +2]
      ::hv3::button ${b}.decreasefont -text "-" -command [list $self font -2]
      pack ${b}.reorient -side right
      pack ${b}.increasefont -side right
      pack ${b}.decreasefont -side right

      pack ${b}.label -side left -fill x
................................................................................
        ${win}.b.decreasefont configure -state disabled
      } else {
        ${win}.b.decreasefont configure -state normal
      }
    }

    method Reorient {} {
      set y [lindex [${win}.pan sash coord 0] 1]
      set h [winfo height ${win}.pan]
      if {$y > $h/2} {
        set y [expr {int($h*0.1)}]
      } else {
        set y [expr {int($h*0.9)}]
      }
      ${win}.pan sash place 0 0 $y
    }


    # This method is called to evaluate a command typed into $myEntryField.
    #
    method Evaluate {} {
      set cmd [$myEntryField get]
................................................................................
        Javascript {
          set isEnabled [gui_current cget -enablejavascript]
          $myOutputWindow insert end "> $cmd\n" javascript
          if {!$isEnabled} {
            $myOutputWindow insert end "    Javascript is not enabled\n" error
          } else {
            set dom [[gui_current hv3] dom]
            set result [$dom javascript $cmd]
            set result [string map {"\n" "\n    "} $result]
            if {[lindex $result 0] eq "JS_ERROR"} {
              $myOutputWindow insert end "    $result\n" error
            } else {
              $myOutputWindow insert end "    $result\n"
            }
          }
................................................................................
      $myCodeViewer tag add wheat "$iLine.0" "$iLine.0 lineend"
    }
    method DisplayCssError {pageid iLine} {
      $self Display css $pageid
      $myCodeViewer yview -pickplace "$iLine.0"
    }

    proc getlogscript {name} {
      foreach {dom idx} [split $name .] {}
      foreach logscript [$dom GetLog] {
        if {[$logscript cget -name] eq $name} {return $logscript}
      }
      return ""
    }

    method Errors {page pageid} {
................................................................................
          $myOutputWindow insert end "Error Message: \"[lindex $r 1]\"\n"
          if {[lindex $r 2] ne ""} {
              $myOutputWindow insert end "    "
              $myOutputWindow insert end "[lindex $r 2]\n"
          }

          foreach {zFile iLine zType zName} [lrange $r 3 end] {
            set target [getlogscript $zFile]
            if {$target ne ""} {
              $myOutputWindow insert end "    "
              set cmd [list $self DisplayJavascriptError $idx $target $iLine]
              $self OutputWindowLink "Line $iLine, [$target cget -heading]" $cmd
              if {$zType ne "" || $zName ne ""} {
                $myOutputWindow insert end "  ($zType $zName)"
              }
................................................................................
	    {To browse the document source code, select a different option}
            {from the "Debug->Application Source Logging" menu and reload}
            {the document.}
        }]
        return
      }
      $self DisplayResources $top 2























    }

    method DisplayResources {frame iIndent} {
      set hv3 [$frame hv3]

      set zIndent [string repeat " " $iIndent]
      set uri [$hv3 uri get]
................................................................................
            $myCodeViewer tag configure $t -foreground red
            $myCodeViewer insert end "  "
        }
        set cmd [list $self Display css [list $frame $id]]
        $self CreateCodeViewerLink "View Source" $cmd
        $myCodeViewer insert end "\n"
      }

      # Links for each javascript file.
      #
      set dom [$hv3 dom]
      set ii 0
      foreach logscript [$dom GetLog] {
        if {[$logscript cget -isevent]} continue
        incr ii
        set cmd [list $self Display javascript [list $ii $logscript]]
        $myCodeViewer insert end $zIndent
        $myCodeViewer insert end "  Javascript: [$logscript cget -heading]  "
        if {[$logscript cget -rc]} {
          set tag [$self CreateCodeViewerLink "(Failed)" [
              list $self Errors javascript [list $ii $dom $logscript]
          ]]
          $myCodeViewer tag configure $tag -foreground red
          $myCodeViewer insert end "  "
        } else {
          $myCodeViewer insert end "(Ok)  "
        }
        $self CreateCodeViewerLink "View Source" $cmd
        set nLine [llength [split [$logscript cget -script] "\n"]]
        $myCodeViewer insert end " ($nLine lines)\n"
      }

      $myCodeViewer insert end "\n"
      foreach child [$frame child_frames] {
        $self DisplayResources $child [expr {$iIndent+4}]
      }
    }
  }

Changes to hv/hv3_dom.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20



21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
347
348
349
350
351
352
353
354
355
356
357
358



359

360
361
362
363
364
365
366
367

368
369

370
371
372
373
374
375
376
377
...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
...
508
509
510
511
512
513
514

515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
...
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1348
1349
1350
1351
1352
1353
1354
1355

1356



1357





1358
1359
1360
namespace eval hv3 { set {version($Id: hv3_dom.tcl,v 1.94 2008/02/03 11:06:56 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# Snit types in this file:
#
#     ::hv3::dom                       -- One object per js interpreter. 
#     ::hv3::dom::logdata              -- Data for js debugger
#     ::hv3::dom::logwin               -- Js debugger GUI
#
# Special widgets used in the ::hv3::dom::logwin GUI:
#
#     ::hv3::dom::stacktrace           -- Debugger "Stack" tab
#     ::hv3::dom::searchbox            -- Debugger "Search" tab
#

package require snit

#-------------------------------------------------------------------------
# Class ::hv3::dom
#



# SYNOPSYS
#
#     set dom [::hv3::dom %AUTO% $hv3]
#
#     $dom script   HV3 ATTR SCRIPT
#     $dom noscript HV3 ATTR SCRIPT
#
#     $dom javascript SCRIPT
#     $dom event EVENT NODE

#     $dom reset
#
#     $dom destroy
#
#     $dom javascriptlog               ;# DEBUGGING ONLY.
#
#     $dom configure -enable BOOLEAN
#
# DESCRIPTION
#
#   Each DOM browsing context (in Hv3, each tab), creates an instance
#   of this class.
#
snit::type ::hv3::dom {

  variable mySee ""


  # Boolean option. Enable this DOM implementation or not.
  option -enable -default 0 -configuremethod SetEnable

  # Logging command.
  option -logcmd -default "" -configuremethod ConfigureLogcmd

  # Instance of [::hv3::browser] associated with this object.
  variable myBrowser ""

  # Used to assign unique ids to each block of script evaluated. 
  # This is used by the script debugging gui.
  variable myNextCodeblockNumber 1

  constructor {browser args} {
    set myBrowser $browser
    set myLogData [::hv3::dom::logdata %AUTO% $self]
    $self configurelist $args
  }

  method browser {} {
    return $myBrowser
  }

  method SetEnable {option value} {
    set options($option) $value
    if {$value} ::hv3::enable_javascript
    if {$mySee ne "" && ![$self HaveScripting]} {
      foreach win [array names myWindows] {
        $mySee make_transient [list ::hv3::DOM::Window $self $win]
      }
      $mySee destroy
      set mySee ""
    }
    if {$mySee eq "" && [$self HaveScripting]} {
      set mySee [::see::interp]
      ::hv3::profile::instrument $mySee
      foreach win [array names myWindows] {
        $mySee window [list ::hv3::DOM::Window $self $win]
      }
    }
  }

  destructor { 
    catch { $mySee destroy }
    catch { $myLogData destroy }
  }

  # Invoked to set the value of the -logcmd option
  method ConfigureLogcmd {option value} {
    set options($option) $value
    if {$mySee ne ""} {
      $mySee log $value
    }
  }

  # Return true if the Tclsee extension is available and 
  # the user has foolishly enabled it.
  method HaveScripting {} {
    return [expr {$options(-enable) && [info commands ::see::interp] ne ""}]
  }

  method InitWindowEvents {body} {
    set script ""
    foreach A {onload onunload} {
      catch {
        set V [$body attr $A]
        append script [subst {
          if (!window.$A) { window.$A = function(event) {$V} }
        }]
      }
    }
    $mySee eval -window [$self node_to_window $body] -noresult $script
  }

  method set_object_property {object property value} {
    if {$mySee eq ""} {
      error "set_object_property before SEE was initialized"
    }
    $mySee set $object $property $value
  }

  # Delete any allocated interpreter and objects. This is called in
  # two circumstances: when deleting this object and from within
  # the [reset] method.
  #
  method clear {} {
    # Delete the old interpreter and the various objects, if they exist.
    # They may not exist, if this is being called from within the
    # object constructor or scripting is disabled.
    # if {$mySee ne ""} {
    #   $mySee make_transient [$self window]
    #   $mySee destroy
    #   set mySee ""
    # }
  }

  method reset {} {
return

    $self clear

    if {[$self HaveScripting]} {

      # Set up the new interpreter with the global "Window" object.
      set mySee [::see::interp]
      $mySee window [$self window]
      set myWindowInitEvents 0

      $mySee log $options(-logcmd)

      # Reset the debugger.
      $self LogReset
    }

    # Reset the counter used to name blobs of code. This way, if
    # a page is reloaded the names are the same, which makes it
    # possible to set breakpoints in the debugger before reloading
    # a page. 
    #
    # Of course, the network might deliver external scripts
    # in a different order. Maybe there should be a debugging option
    # to block while downloading all scripts, even if the "defer"
    # attribute is set.
    #
    set myNextCodeblockNumber 1
  }

  method NewFilename {} {
    return "blob[incr myNextCodeblockNumber]"
  }
  
  # This method is called as a Tkhtml3 "script handler" for elements
  # of type <SCRIPT>. I.e. this should be registered with the html widget
  # as follows:
  #
  #     $htmlwidget handler script script [list $dom script]
  #
  # This is done externally, not by code within this type definition.
  # If scripting is not enabled in this browser, this method is a no-op.
  #
  method script {hv3 attr script} {

    if {$mySee ne ""} {
      $hv3 html write wait
      array set a $attr
      if {[info exists a(src)]} {
        set fulluri [$hv3 resolve_uri $a(src)]
        set handle [::hv3::request %AUTO%             \
            -uri         $fulluri                      \
            -mimetype    text/javascript               \
            -cachecontrol normal                       \
        ]
        if {[$hv3 encoding] ne ""} {
          # puts "load script $fulluri encoding [$hv3 encoding]"
          $handle configure -encoding [$hv3 encoding]
        }
	  
        set fin [mymethod scriptCallback $hv3 $attr $handle]
        $handle configure -finscript $fin
        $hv3 makerequest $handle
        # $self Log "Dispatched script request - $handle" "" "" ""
      } else {
        # return [$self scriptCallback $hv3 $attr "" $script]
        return [$self scriptCallback $hv3 $attr "" $script]

      }
    }
    return ""
  }

  # Script handler for <noscript> elements. If javascript is enabled,
  # do nothing (meaning don't process the contents of the <noscript>
  # block). On the other hand, if js is disabled, feed the contents
  # of the <noscript> block back to the parser using the same
  # Tcl interface used for document.write().
  #
  method noscript {hv3 attr script} {
    if {$mySee ne ""} {
      return ""
    } else {
      $hv3 html write text $script
    }
  }
  
  # If a <SCRIPT> element has a "src" attribute, then the [script]
  # method will have issued a GET request for it. This is the 
  # successful callback.
  #
  method scriptCallback {hv3 attr downloadHandle script} {
    set title ""
    if {$downloadHandle ne ""} { 
      # Handle an HTTP redirect or a Location header:
      #
      if {[$hv3 HandleLocation $downloadHandle]} return
      set title [$downloadHandle cget -uri]
      $downloadHandle release 
    }

    if {$title eq ""} {
      set attributes ""
      foreach {a v} $attr {
................................................................................
        set script [string map {"\r\n" "\n"} $script]
        set script [string map {"\r" "\n"} $script]
        set script [::see::format $script]
      }
    }

    set name [$self NewFilename]
    set w [list ::hv3::DOM::Window $self $hv3]
    set rc [catch {$mySee eval -window $w -noresult -file $name $script} msg]


    $self Log $title $name $script $rc $msg
    $hv3 html write continue
  }

  method javascript {hv3 script} {
    set msg ""
    if {$mySee ne ""} {
      set name [$self NewFilename]
      if {$hv3 eq ""} {set hv3 [$myBrowser hv3]}
      set w [$self hv3_to_window $hv3]
      set rc [catch {$mySee eval -window $w -file $name $script} msg]
    }
    return $msg
  }

  # This method is called when one an event of type $event occurs on the
  # document node $node. Argument $event is one of the following:
  #
  #     onload
................................................................................
      set fs [[$node html] search frameset -index 0]
      if {$fs ne ""} { 
        $self InitWindowEvents $fs
        return
      }
      $self InitWindowEvents $node

      set js_obj [$self node_to_window $node]
    } else {
      set js_obj [::hv3::dom::wrapWidgetNode $self $node]
    }

    # Dispatch the event.
    set rc [catch {
      ::hv3::dom::dispatchHtmlEvent $self $event $js_obj
................................................................................
      set msg ""
    }

    set msg
  }

  method DoFramesetLoadEvents {node} {
    set frame [$self node_to_frame $node]

    # If $frame is a replacement object for an <IFRAME> element, 
    # then fire the load event on the <IFRAME> element.
    if {[$frame cget -iframe] ne ""} {



      $self DispatchHtmlEvent load [::hv3::dom::wrapWidgetNode $self [$frame cget -iframe]]

      return
    }

    set p [$frame parent_frame]
    if {$p eq ""} return
    
    foreach c [$p child_frames] {
      if {0 == [[$c hv3] onload_fired]} return

    }


    set js_obj [$self hv3_to_window [$p hv3]]

    # Dispatch the event.
    $self DispatchHtmlEvent load $js_obj
  }

  # This method is called by the ::hv3::mousemanager object to 
  # dispatch a mouse-event into DOM country. Argument $event
................................................................................
      set name [string map {blob error} [$self NewFilename]]
      $self EventLog "$event $node" $name "" $rc $msg
      set msg "prevent"
    }
    set msg
  }

  #----------------------------------------------------------------
  # Given an html-widget node-handle, return the corresponding 
  # ::hv3::hv3 object. i.e. the owner of the node-handle.
  #
  method node_to_hv3 {node} {
    [winfo parent [$node html]] hv3 me
  }

  method node_to_frame {node} {
    [winfo parent [$node html]] me
  }

  # Given a Tkhtml3 node-handle, return the javascript wrapper 
  # for the containing window. 
  #
  method node_to_window {node} {
    set hv3 [$self node_to_hv3 $node]
    list ::hv3::DOM::Window $self $hv3
  }

  method hv3_to_window {hv3} {
    list ::hv3::DOM::Window $self $hv3
  }

  # The following methods:
  #
  #     [make_window]
  #     [clear_window]
  #     [delete_window]
  #
  # are used to manage the life-time of DOM Window objects.
  #
  method clear_window {hv3} {
    catch {$mySee clear [list ::hv3::DOM::Window $self $hv3]}

    # If javascript is enabled and Window object being cleared
    # is the top-level frame, delete and recreated the SEE interpreter.
    # This is necessary, in case the previous URI was in the 
    # "home://" namespace.
    #
    # Also, reset the debugging gui here.
    #
    if {0 && $mySee ne ""} {
      set frame [winfo parent $hv3]
      if {$frame eq [$frame top_frame]} {
        foreach win [array names myWindows] {
          $mySee make_transient [list ::hv3::DOM::Window $self $hv3]
        }
        $self LogReset
        $mySee destroy
        set mySee ""

        array unset myWindows
        set myWindows($hv3) 1
        if {[$self HaveScripting]} {
          set mySee [::see::interp]
          ::hv3::profile::instrument $mySee
          $mySee log $options(-logcmd)
          $mySee window [list ::hv3::DOM::Window $self $hv3]
        }
      }
    }
  }
  method make_window {hv3} {
    set myWindows($hv3) 1
    if {$mySee ne ""} {
      $mySee window [list ::hv3::DOM::Window $self $hv3]
    }
  }
  method delete_window {hv3} {
    catch { unset myWindows($hv3) }
    catch { $mySee clear          [list ::hv3::DOM::Window $self $hv3] }
    catch { $mySee make_transient [list ::hv3::DOM::Window $self $hv3] }
  }
  variable myWindows -array [list]

  method see    {} { return $mySee }

  #------------------------------------------------------------------
  # Logging system follows.
  #
  variable myLogList ""

  method GetLog {} {return $myLogList}
................................................................................
    lappend myLogList $obj
  }

  method EventLog {heading name script rc result} {
    if {![info exists ::hv3::log_source_option]} return
    if {!$::hv3::log_source_option} return


    set obj [::hv3::dom::logscript %AUTO% -isevent true \
        -rc $rc -heading $heading -script $script -result $result -name $name
    ]
    lappend myLogList $obj

    ::hv3::launch_console
    .console.console Errors javascript [list -1 $self $obj]
  }

  method LogReset {} {
    set myLogList [list]
    return
  }

  # Called by the tree-browser to get event-listener info for the
  # javascript object associated with the specified tkhtml node.
  #
  method eventdump {node} {
    if {$mySee eq ""} {return ""}
    $mySee events [::hv3::dom::wrapWidgetNode $self $node]
  }
................................................................................
  option -heading -default "" 
  option -script  -default "" 
  option -result  -default "" 
  option -name    -default "" 
  option -isevent -default 0 
}

snit::type ::hv3::dom::logdata {

  # Handle for associated (owner) ::hv3::dom object.
  #
  variable myDom ""

  # Ordered list of ::hv3::dom::logscript objects. The scripts 
  # that make up the application being debugged.
  #
  variable myLogScripts [list]

  # Name of top-level debugging GUI window. At any time, this window
  # may or may not exist. This object is responsible for creating
  # it when it is required.
  #
  variable myWindow ""

  # Array of breakpoints set in the script. The array key is
  # "${zFilename}:${iLine}". i.e. to test if there is a breakpoint
  # in file "blob4" line 10, do:
  #
  #     if {[info exists myBreakpoints(blob4:10)]} {
  #         ... breakpoint processing ...
  #     }
  #
  variable myBreakpoints -array [list]

  variable myInReload 0

  constructor {dom} {
    set myDom $dom
    set myWindow ".[string map {: _} $self]_logwindow"
  }

  method Log {heading name script rc result} {
    if {![info exists ::hv3::log_source_option]} return
    if {!$::hv3::log_source_option} return
    set ls [::hv3::dom::logscript %AUTO% \
      -rc $rc -name $name -heading $heading -script $script -result $result
    ]
    lappend myLogScripts $ls
  }

  method dom {} {
    return $myDom
  }

  method Reset {} {
    foreach ls $myLogScripts {
      $ls destroy
    }
    set myLogScripts [list]

    if {$myInReload} {
      if {[llength [array names myBreakpoints]] > 0} {
        [$myDom see] trace [mymethod SeeTrace]
      }
    } else {
      array unset myBreakpoints
    }
  }

  method Popup {} {
    if {![winfo exists $myWindow]} {
      ::hv3::dom::logwin $myWindow $self
    } 
    wm state $myWindow normal
    raise $myWindow
    $myWindow Populate
  }

  destructor {
    $self Reset
  }


  method GetList {} {
    return $myLogScripts
  }

  method Evaluate {script} {
    set res [$myDom javascript "" $script]
    return $res
  }

  method BrowseToNode {node} {
    set hv3 [winfo parent [winfo parent [$node html]]]
    ::HtmlDebug::browse $hv3 $node
  }

  method SeeTrace {eEvent zFilename iLine} {
    if {$eEvent eq "statement"} {
      if {[info exists myBreakpoints(${zFilename}:$iLine)]} {
        # There is a breakpoint set on this line. Pop up the
        # debugging GUI and set the breakpoint stack.
        $self Popup
        $myWindow Breakpoint $zFilename $iLine
      }
    }
  }

  method breakpoints {} {
    return [array names myBreakpoints]
  }

  method add_breakpoint {blobid lineno} {
    set myBreakpoints(${blobid}:${lineno}) 1
    [$myDom see] trace [mymethod SeeTrace]
  }

  method clear_breakpoint {blobid lineno} {
    unset -nocomplain myBreakpoints(${blobid}:${lineno})
    if {[llength [$self breakpoints]]==0} {
      [$myDom see] trace ""
    }
  }

  # Called by the GUI when the user issues a "reload" command.
  # The difference between this and clicking the reload button
  # in the GUI is that breakpoints are persistent when this
  # command is issued.
  #
  method reload {} {
    set myInReload 1
    gui_current reload
    set myInReload 0
  }
}

snit::widget ::hv3::dom::searchbox {

  variable myLogwin 

  constructor {logwin} {
    ::hv3::label ${win}.label
    ::hv3::scrolled listbox ${win}.listbox

    set myLogwin $logwin

    pack ${win}.label   -fill x
    pack ${win}.listbox -fill both -expand true

    ${win}.listbox configure -background white
    bind ${win}.listbox <<ListboxSelect>> [mymethod Select]
  }

  method Select {} {
    set idx  [lindex [${win}.listbox curselection] 0]
    set link [${win}.listbox get $idx]
    set link [string range $link 0 [expr [string first : $link] -1]]
    $myLogwin GotoCmd -silent $link
    ${win}.listbox selection set $idx
  }

  method Search {str} {
    ${win}.listbox delete 0 end

    set nHit 0
    foreach ls [$myLogwin GetList] {
      set blobid [$ls cget -name]
      set iLine 0
      foreach line [split [$ls cget -script] "\n"] {
        incr iLine
        if {[string first $str $line]>=0} {
          ${win}.listbox insert end "$blobid $iLine: $line"
          incr nHit
        }
      }
    }

    return $nHit
  }
}

snit::widget ::hv3::dom::stacktrace {

  variable myLogwin ""

  constructor {logwin} {
    ::hv3::label ${win}.label
    ::hv3::scrolled listbox ${win}.listbox

    set myLogwin $logwin

    pack ${win}.label -fill x
    pack ${win}.listbox -fill both -expand true

    ${win}.listbox configure -background white
    bind ${win}.listbox <<ListboxSelect>> [mymethod Select]
  }

  method Select {} {
    set idx  [lindex [${win}.listbox curselection] 0]
    set link [${win}.listbox get $idx]
    $myLogwin GotoCmd -silent $link
    ${win}.listbox selection set $idx
  }

  method Populate {title stacktrace} {
    ${win}.label configure -text $title
    ${win}.listbox delete 0 end
    foreach {blobid lineno calltype callname} $stacktrace {
      ${win}.listbox insert end "$blobid $lineno"
    }
  }
}

#-------------------------------------------------------------------------
# ::hv3::dom::logwin --
#
#     Top level widget for the debugger window.
#
snit::widget ::hv3::dom::logwin {
  hulltype toplevel

  # Internal widgets from left-hand pane:
  #
  variable myFileList ""                            ;# Listbox with file-list
  variable mySearchbox ""                           ;# Search results
  variable myStackList ""                           ;# Stack trace widget.

  # The text widget used to display code and the label displayed above it.
  #
  variable myCode ""
  variable myCodeTitle ""

  # The two text widgets: One for input and one for output.
  #
  variable myInput ""
  variable myOutput ""

  # ::hv3::dom::logdata object containing the debugging
  # data for the DOM environment being debugged.
  #
  variable myData

  # Index in [$myData GetList] of the currently displayed file:
  #
  variable myCurrentIdx 0

  # Current point in stack trace. Tag this line with "tracepoint"
  # in the $myCode widget.
  #
  variable myTraceFile ""
  variable myTraceLineno ""

  variable myStack ""

  constructor {data} {
    
    set myData $data

    panedwindow ${win}.pan -orient horizontal
    panedwindow ${win}.pan.right -orient vertical

    set nb [::hv3::notebook ${win}.pan.left]
    set myFileList [::hv3::scrolled listbox ${win}.pan.left.files]

    set mySearchbox [::hv3::dom::searchbox ${win}.pan.left.search $self]
    set myStackList [::hv3::dom::stacktrace ${win}.pan.left.stack $self]

    $nb add $myFileList  -text "Files"
    $nb add $mySearchbox -text "Search"
    $nb add $myStackList -text "Stack"

    $myFileList configure -bg white
    bind $myFileList <<ListboxSelect>> [mymethod PopulateText]

    frame ${win}.pan.right.top 
    set myCode [::hv3::scrolled ::hv3::text ${win}.pan.right.top.code]
    set myCodeTitle [::hv3::label ${win}.pan.right.top.label -anchor w]
    pack $myCodeTitle -fill x
    pack $myCode -fill both -expand 1
    $myCode configure -bg white

    $myCode tag configure linenumber -foreground darkblue
    $myCode tag configure tracepoint -background skyblue
    $myCode tag configure stackline  -background wheat
    $myCode tag configure breakpoint -background red

    $myCode tag bind linenumber <1> [mymethod ToggleBreakpoint %x %y]

    frame ${win}.pan.right.bottom 
    set myOutput [::hv3::scrolled ::hv3::text ${win}.pan.right.bottom.output]
    set myInput  [::hv3::text ${win}.pan.right.bottom.input -height 3]
    $myInput configure -bg white
    $myOutput configure -bg white -state disabled -wrap none
    $myOutput tag configure commandtext -foreground darkblue
    $myOutput tag configure commandalert -foreground darkred

    # Set up key bindings for the input window:
    #bind $myInput <Return> [list after idle [mymethod Evaluate]]
    bind $myInput <Return> [mymethod Evaluate]
    bind $myInput <Up>     [list after idle [mymethod HistoryBack]]
    bind $myInput <Down>   [list after idle [mymethod HistoryForward]]

    pack $myInput -fill x -side bottom
    pack $myOutput -fill both -expand 1

    ${win}.pan add ${win}.pan.left -width 200
    ${win}.pan add ${win}.pan.right

    ${win}.pan.right add ${win}.pan.right.top  -height 200 -width 600
    ${win}.pan.right add ${win}.pan.right.bottom -height 350

    pack ${win}.pan -fill both -expand 1

    bind ${win} <Escape> [list destroy ${win}]

    focus $myInput
    $myInput insert end "help"
    $self Evaluate
  }

  method GetList {} { return [$myData GetList] }

  method Populate {} {
    $myFileList delete 0 end

    # Populate the "Files" list-box.
    #
    foreach ls [$myData GetList] {
      set name    [$ls cget -name] 
      set heading [$ls cget -heading] 
      set rc   [$ls cget -rc] 

      $myFileList insert end "$name - $heading"

      if {$name eq $myTraceFile} {
        $myFileList selection set end
      }
  
      if {$rc} {
        $myFileList itemconfigure end -foreground red -selectforeground red
      }
    }
  }

  method PopulateText {} {
    $myCode configure -state normal
    $myCode delete 0.0 end
    set idx [lindex [$myFileList curselection] 0]
    if {$idx ne ""} {
      set ls [lindex [$myData GetList] $idx]
      $myCodeTitle configure -text [$ls cget -heading]

      set name [$ls cget -name]
      set stacklines [list]
      foreach {n l X Y} $myStack {
        if {$n eq $name} { lappend stacklines $l }
      }

      set script [$ls cget -script]
      set N 1
      foreach line [split $script "\n"] {
        $myCode insert end [format "% 5d   " $N] linenumber
        if {[$ls cget -name] eq $myTraceFile && $N == $myTraceLineno} {
          $myCode insert end "$line\n" tracepoint
        } elseif {[lsearch $stacklines $N] >= 0} {
          $myCode insert end "$line\n" stackline
        } else {
          $myCode insert end "$line\n"
        }
        incr N
      }
      set myCurrentIdx $idx
    }

    # The following line throws an error if no chars are tagged "tracepoint".
    catch { $myCode yview -pickplace tracepoint.first }
    $myCode configure -state disabled
    $self PopulateBreakpointTag
  }

  # This proc is called after either:
  #
  #     * The contents of the code window change, or
  #     * A breakpoint is added or cleared from the debugger.
  #
  # It ensures the "breakpoint" tag is set on the line-number
  # of any line that has a breakpoint set.
  #
  method PopulateBreakpointTag {} {
    set ls     [lindex [$myData GetList] $myCurrentIdx]
    set blobid [$ls cget -name]

    $myCode tag remove breakpoint 0.0 end
    foreach key [$myData breakpoints] {
      foreach {b i} [split $key :] {}
      if {$b eq $blobid} {
        $myCode tag add breakpoint ${i}.0 ${i}.5
      }
    }
  }

  method ToggleBreakpoint {x y} {
    set ls     [lindex [$myData GetList] $myCurrentIdx]
    set lineno [lindex [split [$myCode index @${x},${y}] .] 0]
    set blobid [$ls cget -name]

    if {[lsearch [$myData breakpoints] "${blobid}:${lineno}"]>=0} {
      $myData clear_breakpoint ${blobid} ${lineno}
    } else {
      $myData add_breakpoint ${blobid} ${lineno}
    }
    $self PopulateBreakpointTag
  }

  # This is called when the user issues a [result] command.
  #
  method ResultCmd {cmd} {
    # The (optional) argument is one of the blob names. If
    # it is not specified, use the currently displayed js blob 
    # as a default.
    #
    set arg [lindex $cmd 0]
    if {$arg eq ""} {
      set idx $myCurrentIdx
      if {$idx eq ""} {set idx [llength [$myData GetList]]}
    } else {
      set idx 0
      foreach ls [$myData GetList] {
        if {[$ls cget -name] eq $arg} break
        incr idx
      }
    }
    set ls [lindex [$myData GetList] $idx]
    if {$ls eq ""} {
      error "No such file: \"$arg\""
    }

    # Echo the command to the output panel.
    #
    $myOutput insert end "result: [$ls cget -name]\n" commandtext

    $myOutput insert end "   rc       : " commandtext
    $myOutput insert end "[$ls cget -rc]\n"
    if {[$ls cget -rc] && [lindex [$ls cget -result] 0] eq "JS_ERROR"} {
      set res [$ls cget -result]
      set msg        [lindex $res 1]
      set zErrorInfo [lindex $res 2]
      set stacktrace [lrange $res 3 end]
      set stack ""
      foreach {file lineno a b} $stacktrace {
        set stack "-> $file:$lineno $stack"
      }
      $myOutput insert end "   result   : " commandtext
      $myOutput insert end "$msg\n"
      $myOutput insert end "   stack    : " commandtext
      $myOutput insert end "[string range $stack 3 end]\n"
      $myOutput insert end "   errorInfo: " commandtext
      $myOutput insert end "$zErrorInfo\n"

      set blobid ""
      set r [$ls cget -result]
      regexp {(blob[[:digit:]]*):([[:digit:]]*):} $r X blobid lineno

      if {$blobid ne ""} {
        set stacktrace [linsert $stacktrace 0 $blobid $lineno "" ""]
      }

      if {[llength $stacktrace] > 0} {
        set blobid [lindex $stacktrace 0]
        set lineno [lindex $stacktrace 1]
        set myStack $stacktrace
        $myStackList Populate "Result of [$ls cget -name]:" $stacktrace
        [winfo parent $myStackList] select $myStackList
      }

      if {$blobid ne ""} {
        $self GotoCmd -silent [list $blobid $lineno]
      }
      
    } else {
      $myOutput insert end "   result: [$ls cget -result]\n"
    }
  }
 
  # This is called when the user issues a [clear] command.
  #
  method ClearCmd {cmd} {
    $myOutput delete 0.0 end
  }

  # This is called when the user issues a [javascript] command.
  #
  method JavascriptCmd {cmd} {
    set js [string trim $cmd]
    set res [$myData Evaluate $js]
    $myOutput insert end "javascript: $js\n" commandtext
    if {[lindex $res 0] eq "object" && [llength $res] == 2} {
      $self PrintObject [lindex $res 1]
    } else {
      $myOutput insert end "    [string trim $res]\n"
    }
  }

  method PrintObject {obj} {
    set state [$myOutput cget -state]
    if {$state eq "disabled"} {
      $myOutput configure -state normal
    }
   
    $myOutput insert end "    object $obj\n"

    set nMax 0
    set propertylist [lsort [eval $obj List]]
    foreach property $propertylist {
      if {[string length $property] > $nMax} {
        set nMax [string length $property]
      }
    }
    incr nMax 2
    foreach property $propertylist {
      set value [eval $obj Get $property]
      $myOutput insert end [format "        %-${nMax}s" $property]
      if {[lindex $value 0] eq "object" && [llength $value] == 2} {
        set tag [string map [list " " _ ":" _] $value]
 
        set classname [lindex $value 1 0]
        set classname [
          string range $classname [expr {[string last : $classname]+1}] end
        ]
       
        $myOutput insert end "object "
        $myOutput insert end $classname $tag

        $myOutput tag bind $tag <1> [list $self PrintObject [lindex $value 1]]
        $myOutput tag bind $tag <Enter> [list $myOutput configure -cursor hand2]
        $myOutput tag bind $tag <Leave> [list $myOutput configure -cursor ""]
        $myOutput tag configure $tag -underline 1 -foreground darkblue
      } else {
        $myOutput insert end $value
      }
      $myOutput insert end "\n"
    }
    $myOutput yview -pickplace end
    $myOutput configure -state $state
  }

  method GotoCmd {cmd {cmd2 ""}} {
    if {$cmd2 ne ""} {set cmd $cmd2}
    set blobid [lindex $cmd 0]
    set lineno [lindex $cmd 1]
    if {$lineno eq ""} {
      set lineno 1
    }

    if {$cmd2 eq ""} {
      $myOutput insert end "goto: $blobid $lineno\n" commandtext
    }

    set idx 0
    set ok 0
    foreach ls [$myData GetList] {
      if {[$ls cget -name] eq $blobid} {set ok 1 ; break}
      incr idx
    }

    if {!$ok} {
      $myOutput insert end "        No such blob: $blobid"
      return
    }

    set myTraceFile $blobid
    set myTraceLineno $lineno
    if {$cmd2 eq ""} {
      $self Populate
    } else {
      $myFileList selection clear 0 end
      $myFileList selection set $idx
    }
    $self PopulateText
  }

  method ErrorCmd {cmd} {
  }

  method SearchCmd {cmd} {
    set n [$mySearchbox Search $cmd]
    ${win}.pan.left select $mySearchbox
    $myOutput insert end "search: $cmd\n" commandtext
    $myOutput insert end "    $n hits.\n"
  }

  method TreeCmd {node} {
    $myOutput insert end "tree: $node\n" commandtext
    $myData BrowseToNode $node
  }

  method TclCmd {args} {
    $myOutput insert end "tcl: $args\n" commandtext
    set res [eval uplevel #0 $args]
    $myOutput insert end "    $res\n" 
  }

  method ReloadCmd {args} {
    $myData reload
  }

  method DebugCmd {args} {
    $myOutput insert end "debug: $args\n" commandtext
    set see [[$myData dom] see] 
    switch -- [lindex $args 0] {

      alloc {
        set data [eval $see debug $args]
        foreach {key value} $data {
          set key [format "    % -30s" $key]
          $myOutput insert end $key commandtext 
          $myOutput insert end ": $value\n"
        }
      }

      default {
        set objlist [eval [[$myData dom] see] debug $args]
        foreach obj $objlist {
          $myOutput insert end "    $obj\n"
        }
      }
    }
  }

  method Evaluate {} {
    set script [string trim [$myInput get 0.0 end]]
    $myInput delete 0.0 end
    $myInput mark set insert 0.0

    set idx [string first " " $script]
    if {$idx < 0} {
      set idx [string length $script]
    }
    set zWord [string range $script 0 [expr $idx-1]]
    set nWord [string length $zWord]

    $myOutput configure -state normal

    set cmdlist [list \
      clear      2 ""                     ClearCmd      \
      cont       2 ""                     ContCmd       \
      goto       1 "BLOBID ?LINE-NUMBER?" GotoCmd       \
      js         1 "JAVASCRIPT..."        JavascriptCmd \
      debug      1 "SUB-COMMAND"          DebugCmd      \
      reload     2 ""                     ReloadCmd     \
      result     1 "BLOBID"               ResultCmd     \
      search     1 "STRING"               SearchCmd     \
      tree       2 "NODE"                 TreeCmd       \
      tcl        2 "TCL-SCRIPT"           TclCmd        \
    ]
    set done 0
    foreach {cmd nMin NOTUSED method} $cmdlist {
      if {$nWord>=$nMin && [string first $zWord $cmd]==0} {
        $self $method [string trim [string range $script $nWord end]]
        set done 1
        break
      }
    }
    
    if {!$done} {
        # An unknown command (or "help"). Print a summary of debugger commands.
        #
        $myOutput insert end "help:\n" commandtext
        foreach {cmd NOTUSED help NOTUSED} $cmdlist {
        $myOutput insert end "          $cmd $help\n"
      }
      set x "Unambiguous prefixes of the above commands are also accepted.\n"
      $myOutput insert end "        $x"
    }

    $myOutput yview -pickplace end
    $myOutput insert end "\n"
    $myOutput configure -state disabled

    $self HistoryAdd $script
  }


  # History list for input box. Interface is:
  #
  #     $self HistoryAdd $script       (add command to end of history list)
  #     $self HistoryBack              (bind to <back> key>)
  #     $self HistoryForward           (bind to <forward> key)
  #
  variable myHistory [list]
  variable myHistoryIdx 0
  method HistoryAdd {script} {
    lappend myHistory $script
    set myHistoryIdx [llength $myHistory]
  }
  method HistoryBack {} {
    if {$myHistoryIdx==0} return
    incr myHistoryIdx -1
    $myInput delete 0.0 end
    $myInput insert end [lindex $myHistory $myHistoryIdx]
  }
  method HistoryForward {} {
    if {$myHistoryIdx==[llength $myHistory]} return
    incr myHistoryIdx
    $myInput delete 0.0 end
    $myInput insert end [lindex $myHistory $myHistoryIdx]
  }
  #
  # End of history list for input box.


  # Variable used for breakpoint code.
  variable myBreakpointVwait
  method ContCmd {args} { 
    $myOutput insert end "cont:\n" commandtext
    set myBreakpointVwait 1 

    set myTraceFile ""
    set myTraceLineno ""
    set myStack ""
    $myStackList Populate "" $myStack
    $myCode tag remove tracepoint 0.0 end
    $myCode tag remove stackline 0.0 end
  }

  # This is called when the SEE interpreter has been stopped at
  # a breakpoint. Js execution will continue after this method 
  # returns.
  #
  method Breakpoint {zBlobid iLine} {
    set myBreakpointVwait 0

    set myStack [list $zBlobid $iLine "" ""]
    $myStackList Populate "Breakpoint $zBlobid $iLine" $myStack
    [winfo parent $myStackList] select $myStackList
    $self GotoCmd -silent [list $zBlobid $iLine]

    $myOutput configure -state normal
    $myOutput insert end "breakpoint: $zBlobid $iLine\n\n" commandalert
    $myOutput configure -state disabled

    vwait [myvar myBreakpointVwait]
  }
}
#-----------------------------------------------------------------------

#-----------------------------------------------------------------------
# Pull in the object definitions.
#
proc ::hv3::dom_init {{init_docs 0}} {
  set ::hv3::dom::CREATE_DOM_DOCS 0
  if {$init_docs} {set ::hv3::dom::CREATE_DOM_DOCS 1}

................................................................................

namespace eval ::hv3::DOM {
  # Given an html-widget node-handle, return the corresponding 
  # ::hv3::DOM::HTMLDocument object. i.e. the thing needed for
  # the Node.ownerDocument javascript property of an HTMLElement or
  # Text Node.
  #
  proc node_to_document {dom node} {

    list ::hv3::DOM::HTMLDocument \



        $dom [winfo parent [winfo parent [$node html]]]





  }
}

|





|
<
<
<
<
<
<







>
>
>




|
<



>










|
<
|
<
>


>
|
|




<
<
<




|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<





<










<
<
<
<
<
<










|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|











|
<
<
|
|
|
|
|
|
|
|
|
|
<
|
|

|
|
|
<
|
<
<
>
|
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<





|




|







 







<
|
>


|


|
<
<
|
<
<
|
<







 







|







 







|




>
>
>
|
>







|
>
|
|
>
|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







 







>









<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
>
|
>
>
>
|
>
>
>
>
>



1
2
3
4
5
6
7






8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38

39
40
41
42
43
44
45
46
47
48



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66












67
68
69
70
71

72
73
74
75
76
77
78
79
80
81






82
83
84
85
86
87
88
89
90
91
92
93
94





















































95
96
97
98
99
100
101
102
103
104
105
106
107
108


109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124

125


126
127

128
129














130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
...
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170


171


172

173
174
175
176
177
178
179
...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
...
312
313
314
315
316
317
318












































































319
320
321
322
323
324
325
326
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351





352
353
354
355
356
357
358
...
373
374
375
376
377
378
379




































































































































































































































































































































































































































































































































































































































































































































































380
381
382
383
384
385
386
...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
namespace eval hv3 { set {version($Id: hv3_dom.tcl,v 1.95 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# Snit types in this file:
#
#     ::hv3::dom                       -- One object per js interpreter. 
#     ::hv3::dom::logscript            -- Logging data for debugging.






#

package require snit

#-------------------------------------------------------------------------
# Class ::hv3::dom
#
#   A single instance of this class is created for each javascript
#   enabled ::hv3::hv3 widget. The javascript module.
#
# SYNOPSYS
#
#     set dom [::hv3::dom %AUTO% $hv3]
#
#     $dom script ATTR SCRIPT

#
#     $dom javascript SCRIPT
#     $dom event EVENT NODE
#     $dom set_object_property {object property value}
#     $dom reset
#
#     $dom destroy
#
#     $dom javascriptlog               ;# DEBUGGING ONLY.
#
#     $dom configure -enable BOOLEAN
#
# DESCRIPTION
#
snit::type ::hv3::dom {



  # Javascript interpreter.
  variable mySee ""

  # Instance of [::hv3::hv3] that contains the window used as the
  # global object by this interpreter.
  variable myHv3 ""

  # Logging command.
  option -logcmd -default "" -configuremethod ConfigureLogcmd




  # Used to assign unique ids to each block of script evaluated. 
  # This is used by the script debugging gui.
  variable myNextCodeblockNumber 1

  constructor {hv3 args} {

    # Call [::hv3::enable_javascript] to make sure the hv3_dom_XXX.tcl
    # files have been loaded.
    ::hv3::enable_javascript

    set myHv3 $hv3
    set mySee [::see::interp [list ::hv3::DOM::Window $self $hv3]]

    $self configurelist $args

    set frame [$myHv3 cget -frame]
    if {$frame ne ""} {
      $frame update_parent_dom $mySee












    }
  }

  destructor { 
    catch { $mySee destroy }

  }

  # Invoked to set the value of the -logcmd option
  method ConfigureLogcmd {option value} {
    set options($option) $value
    if {$mySee ne ""} {
      $mySee log $value
    }
  }







  method InitWindowEvents {body} {
    set script ""
    foreach A {onload onunload} {
      catch {
        set V [$body attr $A]
        append script [subst {
          if (!window.$A) { window.$A = function(event) {$V} }
        }]
      }
    }
    $mySee eval -noresult $script
  }






















































  method NewFilename {} {
    return "$self.[incr myNextCodeblockNumber]"
  }
  
  # This method is called as a Tkhtml3 "script handler" for elements
  # of type <SCRIPT>. I.e. this should be registered with the html widget
  # as follows:
  #
  #     $htmlwidget handler script script [list $dom script]
  #
  # This is done externally, not by code within this type definition.
  # If scripting is not enabled in this browser, this method is a no-op.
  #
  method script {attr script} {


    $myHv3 html write wait
    array set a $attr
    if {[info exists a(src)]} {
      set fulluri [$myHv3 resolve_uri $a(src)]
      set handle [::hv3::request %AUTO%              \
          -uri         $fulluri                      \
          -mimetype    text/javascript               \
          -cachecontrol normal                       \
      ]
      if {[$myHv3 encoding] ne ""} {

        $handle configure -encoding [$myHv3 encoding]
      }
	  
      set fin [mymethod ScriptCallback $attr $handle]
      $handle configure -finscript $fin
      $myHv3 makerequest $handle

    } else {


      return [$self ScriptCallback $attr "" $script]
    }

    return ""
  }














  
  # If a <SCRIPT> element has a "src" attribute, then the [script]
  # method will have issued a GET request for it. This is the 
  # successful callback.
  #
  method ScriptCallback {attr downloadHandle script} {
    set title ""
    if {$downloadHandle ne ""} { 
      # Handle an HTTP redirect or a Location header:
      #
      if {[$myHv3 HandleLocation $downloadHandle]} return
      set title [$downloadHandle cget -uri]
      $downloadHandle release 
    }

    if {$title eq ""} {
      set attributes ""
      foreach {a v} $attr {
................................................................................
        set script [string map {"\r\n" "\n"} $script]
        set script [string map {"\r" "\n"} $script]
        set script [::see::format $script]
      }
    }

    set name [$self NewFilename]

    set rc [catch {$mySee eval -noresult -file $name $script} msg]
    if {$rc} {puts "MSG: $msg"}

    $self Log $title $name $script $rc $msg
    $myHv3 html write continue
  }

  method javascript {script} {


    set name [$self NewFilename]


    set rc [catch {$mySee eval -file $name $script} msg]

    return $msg
  }

  # This method is called when one an event of type $event occurs on the
  # document node $node. Argument $event is one of the following:
  #
  #     onload
................................................................................
      set fs [[$node html] search frameset -index 0]
      if {$fs ne ""} { 
        $self InitWindowEvents $fs
        return
      }
      $self InitWindowEvents $node

      set js_obj [::hv3::DOM::node_to_window $node]
    } else {
      set js_obj [::hv3::dom::wrapWidgetNode $self $node]
    }

    # Dispatch the event.
    set rc [catch {
      ::hv3::dom::dispatchHtmlEvent $self $event $js_obj
................................................................................
      set msg ""
    }

    set msg
  }

  method DoFramesetLoadEvents {node} {
    set frame [[winfo parent [$node html]] me]

    # If $frame is a replacement object for an <IFRAME> element, 
    # then fire the load event on the <IFRAME> element.
    if {[$frame cget -iframe] ne ""} {
      set iframe [$frame cget -iframe]
      set hv3 [[winfo parent [$iframe html]] hv3 me]

      set js_obj [::hv3::dom::wrapWidgetNode [$hv3 dom] $iframe]
      $hv3 dom DispatchHtmlEvent load $js_obj
      return
    }

    set p [$frame parent_frame]
    if {$p eq ""} return
    
    foreach c [$p child_frames] {
      if {0 == [[$c hv3] onload_fired]} {
        return
      }
    }

    set js_obj [::hv3::DOM::hv3_to_window [$p hv3]]

    # Dispatch the event.
    $self DispatchHtmlEvent load $js_obj
  }

  # This method is called by the ::hv3::mousemanager object to 
  # dispatch a mouse-event into DOM country. Argument $event
................................................................................
      set name [string map {blob error} [$self NewFilename]]
      $self EventLog "$event $node" $name "" $rc $msg
      set msg "prevent"
    }
    set msg
  }













































































  method see {} { return $mySee }

  #------------------------------------------------------------------
  # Logging system follows.
  #
  variable myLogList ""

  method GetLog {} {return $myLogList}
................................................................................
    lappend myLogList $obj
  }

  method EventLog {heading name script rc result} {
    if {![info exists ::hv3::log_source_option]} return
    if {!$::hv3::log_source_option} return

    puts "error: $result"
    set obj [::hv3::dom::logscript %AUTO% -isevent true \
        -rc $rc -heading $heading -script $script -result $result -name $name
    ]
    lappend myLogList $obj

    ::hv3::launch_console
    .console.console Errors javascript [list -1 $self $obj]
  }






  # Called by the tree-browser to get event-listener info for the
  # javascript object associated with the specified tkhtml node.
  #
  method eventdump {node} {
    if {$mySee eq ""} {return ""}
    $mySee events [::hv3::dom::wrapWidgetNode $self $node]
  }
................................................................................
  option -heading -default "" 
  option -script  -default "" 
  option -result  -default "" 
  option -name    -default "" 
  option -isevent -default 0 
}





































































































































































































































































































































































































































































































































































































































































































































































#-----------------------------------------------------------------------
# Pull in the object definitions.
#
proc ::hv3::dom_init {{init_docs 0}} {
  set ::hv3::dom::CREATE_DOM_DOCS 0
  if {$init_docs} {set ::hv3::dom::CREATE_DOM_DOCS 1}

................................................................................

namespace eval ::hv3::DOM {
  # Given an html-widget node-handle, return the corresponding 
  # ::hv3::DOM::HTMLDocument object. i.e. the thing needed for
  # the Node.ownerDocument javascript property of an HTMLElement or
  # Text Node.
  #
  proc node_to_document {node} {
    set hv3 [[winfo parent [$node html]] hv3 me]
    list ::hv3::DOM::HTMLDocument [$hv3 dom] $hv3
  }

  proc node_to_window {node} {
    set hv3 [[winfo parent [$node html]] hv3 me]
    list ::hv3::DOM::Window [$hv3 dom] $hv3
  }

  proc hv3_to_window {hv3} {
    list ::hv3::DOM::Window [$hv3 dom] $hv3
  }
}

Changes to hv/hv3_dom_containers.tcl.

1
2
3
4
5
6
7
8
...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
namespace eval hv3 { set {version($Id: hv3_dom_containers.tcl,v 1.10 2007/11/12 10:16:20 danielk1977 Exp $)} 1 }

# This file contains the implementation of the two DOM specific
# container objects:
#
#     NodeList               (DOM Core 1)
#     HTMLCollection         (DOM HTML 1)
#
................................................................................
  }

  dom_get * {
    set frames [$myFrame child_frames]
    if {[string is integer $property]} {
      set f [lindex $frames [expr {int($property)}]]
      if {$f eq ""} return ""
      return [list object [$myDom hv3_to_window [$f hv3]]]
    }

    foreach f $frames {
      if {$property eq [$f cget -name]} {
        return [list object [$myDom hv3_to_window [$f hv3]]]
      }
    }

    return ""
  }
}

|







 







|




|







1
2
3
4
5
6
7
8
...
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
namespace eval hv3 { set {version($Id: hv3_dom_containers.tcl,v 1.11 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

# This file contains the implementation of the two DOM specific
# container objects:
#
#     NodeList               (DOM Core 1)
#     HTMLCollection         (DOM HTML 1)
#
................................................................................
  }

  dom_get * {
    set frames [$myFrame child_frames]
    if {[string is integer $property]} {
      set f [lindex $frames [expr {int($property)}]]
      if {$f eq ""} return ""
      return [list bridge [[$f hv3 dom] see]]
    }

    foreach f $frames {
      if {$property eq [$f cget -name]} {
        return [list bridge [[$f hv3 dom] see]]
      }
    }

    return ""
  }
}

Changes to hv/hv3_dom_core.tcl.

1
2
3
4
5
6
7
8
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
namespace eval hv3 { set {version($Id: hv3_dom_core.tcl,v 1.39 2008/02/03 11:06:56 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# DOM Level 1 Core
#
# This file contains the Hv3 implementation of the DOM Level 1 Core. Where
# possible, Hv3 tries hard to be compatible with W3C and Gecko. Gecko
# is pretty much a clean super-set of W3C for this module.
................................................................................
      set clone [[$myNode html] fragment $zHtml]
    }
    
    list object [::hv3::dom::wrapWidgetNode $myDom $clone]
  }

  dom_get ownerDocument { 
    list object [node_to_document $myDom $myNode]
  }
}
namespace eval ::hv3::DOM {

  proc WidgetNode_ToHtml {node isDeep} {
    set tag [$node tag]
    if {$tag eq ""} {
|







 







|







1
2
3
4
5
6
7
8
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
namespace eval hv3 { set {version($Id: hv3_dom_core.tcl,v 1.40 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# DOM Level 1 Core
#
# This file contains the Hv3 implementation of the DOM Level 1 Core. Where
# possible, Hv3 tries hard to be compatible with W3C and Gecko. Gecko
# is pretty much a clean super-set of W3C for this module.
................................................................................
      set clone [[$myNode html] fragment $zHtml]
    }
    
    list object [::hv3::dom::wrapWidgetNode $myDom $clone]
  }

  dom_get ownerDocument { 
    list object [node_to_document $myNode]
  }
}
namespace eval ::hv3::DOM {

  proc WidgetNode_ToHtml {node isDeep} {
    set tag [$node tag]
    if {$tag eq ""} {

Changes to hv/hv3_dom_html.tcl.

1
2
3
4
5
6
7
8
...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
....
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
namespace eval hv3 { set {version($Id: hv3_dom_html.tcl,v 1.47 2008/02/03 11:06:56 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# DOM Level 1 Html
#
# This file contains the Hv3 implementation of the DOM Level 1 Html. Where
# possible, Hv3 tries hard to be compatible with W3C and Gecko. Gecko
# is pretty much a clean super-set of W3C for this module.
................................................................................
    foreach {k v} [$myNode attr] {
      if {[info exists ::hv3::DOM::HTMLElement_EventAttrArray($k)]} {
        lappend R $k $v
      }
    }
    return $R
  }
  dom_scope {
    list [$myDom node_to_window $myNode]
  }
}

::hv3::dom2::stateless HTMLElement $HTMLElement

set HTMLElement "Inherit HTMLElement { $HTMLElement }"

namespace eval ::hv3::DOM {
................................................................................
    if {$f eq ""} { 
      set f null
    } else {
      list object [::hv3::dom::wrapWidgetNode $dom $f]
    }
  }
  proc HTMLElement_control_scope {dom node} {
    set w [$dom node_to_window $node]
    set scope [list \
      [::hv3::dom::wrapWidgetNode $dom $node] $w [node_to_document $dom $node]
    ]

    set f [lindex [::hv3::get_form_nodes $node] 0]
    if {$f ne ""} { 
      set scope [linsert $scope 1 [::hv3::dom::wrapWidgetNode $dom $f]]
    }
    return $scope
................................................................................

::hv3::dom2::stateless HTMLHtmlElement $HTMLElement { 
  Inherit HTMLElement {
    dom_get parentNode {
      if {$myNode eq [[$myNode html] node]} {
        # TODO: Maybe this is not quite cacheable... But caching it saves
        # calling this code for every single event propagation....
        list cache object [node_to_document $myDom $myNode]
      } else {
        list null
      }
    }
  }
}
::hv3::dom2::stateless HTMLHeadElement      $HTMLElement { #TODO }
|







 







<
<
<







 







<

|







 







|







1
2
3
4
5
6
7
8
...
369
370
371
372
373
374
375



376
377
378
379
380
381
382
...
725
726
727
728
729
730
731

732
733
734
735
736
737
738
739
740
....
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
namespace eval hv3 { set {version($Id: hv3_dom_html.tcl,v 1.48 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

#--------------------------------------------------------------------------
# DOM Level 1 Html
#
# This file contains the Hv3 implementation of the DOM Level 1 Html. Where
# possible, Hv3 tries hard to be compatible with W3C and Gecko. Gecko
# is pretty much a clean super-set of W3C for this module.
................................................................................
    foreach {k v} [$myNode attr] {
      if {[info exists ::hv3::DOM::HTMLElement_EventAttrArray($k)]} {
        lappend R $k $v
      }
    }
    return $R
  }



}

::hv3::dom2::stateless HTMLElement $HTMLElement

set HTMLElement "Inherit HTMLElement { $HTMLElement }"

namespace eval ::hv3::DOM {
................................................................................
    if {$f eq ""} { 
      set f null
    } else {
      list object [::hv3::dom::wrapWidgetNode $dom $f]
    }
  }
  proc HTMLElement_control_scope {dom node} {

    set scope [list \
      [::hv3::dom::wrapWidgetNode $dom $node] [node_to_document $node]
    ]

    set f [lindex [::hv3::get_form_nodes $node] 0]
    if {$f ne ""} { 
      set scope [linsert $scope 1 [::hv3::dom::wrapWidgetNode $dom $f]]
    }
    return $scope
................................................................................

::hv3::dom2::stateless HTMLHtmlElement $HTMLElement { 
  Inherit HTMLElement {
    dom_get parentNode {
      if {$myNode eq [[$myNode html] node]} {
        # TODO: Maybe this is not quite cacheable... But caching it saves
        # calling this code for every single event propagation....
        list cache object [node_to_document $myNode]
      } else {
        list null
      }
    }
  }
}
::hv3::dom2::stateless HTMLHeadElement      $HTMLElement { #TODO }

Changes to hv/hv3_dom_ns.tcl.

1
2
3
4
5
6
7
8
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
namespace eval hv3 { set {version($Id: hv3_dom_ns.tcl,v 1.41 2008/02/03 11:19:58 danielk1977 Exp $)} 1 }

#---------------------------------
# List of DOM objects in this file:
#
#     Navigator
#     Window
#     Location
................................................................................
  }

  -- Returns the same value as reading the <I>href</I> property.
  dom_call toString {THIS} { ::hv3::DOM::Location $myDom $myHv3 DefaultValue }
}
namespace eval ::hv3::DOM {
  proc Location_assign {hv3 loc} {
    set f [winfo parent $hv3]

    # TODO: When assigning a URI from javascript, resolve it relative 
    # to the top-level document... This has got to be wrong... Maybe
    # it is supposed to be the window object in scope...
    #
    # Test case in jsunit source: "jsunit/tests/jsUnitTestLoadData.html"
    #
................................................................................
  -- A reference to the parent of the current window or subframe. If the
  -- window does not have a parent, then a reference to the window
  -- itself is returned.
  dom_get parent {
    set frame [$myHv3 cget -frame]
    set parent [$frame parent_frame]
    if {$parent eq ""} {set parent $frame}
    list object [$myDom hv3_to_window [$parent hv3]]

  }

  -- A reference to the outermost window in the frameset. For ordinary
  -- HTML documents (not framesets) this property is set to a reference
  -- to this object (same as the <I>window</I> and <I>self</I> properties).
  dom_get top { 
    set frame [$myHv3 cget -frame]
    set top [$frame top_frame]
    list object [$myDom hv3_to_window [$top hv3]]
  }

  -- A reference to this object.
  dom_get self   { list object [list ::hv3::DOM::Window $myDom $myHv3] }

  -- A reference to this object.
  dom_get window { list object [list ::hv3::DOM::Window $myDom $myHv3] }
|







 







|







 







|
>






|
|
|







1
2
3
4
5
6
7
8
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
namespace eval hv3 { set {version($Id: hv3_dom_ns.tcl,v 1.42 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

#---------------------------------
# List of DOM objects in this file:
#
#     Navigator
#     Window
#     Location
................................................................................
  }

  -- Returns the same value as reading the <I>href</I> property.
  dom_call toString {THIS} { ::hv3::DOM::Location $myDom $myHv3 DefaultValue }
}
namespace eval ::hv3::DOM {
  proc Location_assign {hv3 loc} {
    set f [$hv3 cget -frame]

    # TODO: When assigning a URI from javascript, resolve it relative 
    # to the top-level document... This has got to be wrong... Maybe
    # it is supposed to be the window object in scope...
    #
    # Test case in jsunit source: "jsunit/tests/jsUnitTestLoadData.html"
    #
................................................................................
  -- A reference to the parent of the current window or subframe. If the
  -- window does not have a parent, then a reference to the window
  -- itself is returned.
  dom_get parent {
    set frame [$myHv3 cget -frame]
    set parent [$frame parent_frame]
    if {$parent eq ""} {set parent $frame}
    set see [[$parent hv3 dom] see]
    list bridge $see
  }

  -- A reference to the outermost window in the frameset. For ordinary
  -- HTML documents (not framesets) this property is set to a reference
  -- to this object (same as the <I>window</I> and <I>self</I> properties).
  dom_get top { 
    set topframe [[$myHv3 cget -frame] top_frame]
    set see [[$topframe hv3 dom] see]
    list bridge $see
  }

  -- A reference to this object.
  dom_get self   { list object [list ::hv3::DOM::Window $myDom $myHv3] }

  -- A reference to this object.
  dom_get window { list object [list ::hv3::DOM::Window $myDom $myHv3] }

Changes to hv/hv3_dom_xmlhttp.tcl.

1
2
3
4
5
6
7
8
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
namespace eval hv3 { set {version($Id: hv3_dom_xmlhttp.tcl,v 1.17 2007/12/17 04:43:07 danielk1977 Exp $)} 1 }

::hv3::dom2::stateless Document {
  %NODE%
  %NODE_PROTOTYPE%
  %DOCUMENT%
}

................................................................................
      $myDom Log "XMLHttpRequest readystatechange" $name "event" $rc $msg
    }
  }
}

set ::hv3::dom::next_xmlhttp_id 0
proc ::hv3::dom::newXMLHttpRequest {dom hv3} {
  set see [$dom see]

  # Name of the state-array for the new object.
  set statevar "::hv3::DOM::xmlhttprequest_[incr ::hv3::dom::next_xmlhttp_id]"
  upvar #0 $statevar state

  # Intialize the new object state.
  set state(async)          0
|







 







<







1
2
3
4
5
6
7
8
...
257
258
259
260
261
262
263

264
265
266
267
268
269
270
namespace eval hv3 { set {version($Id: hv3_dom_xmlhttp.tcl,v 1.18 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

::hv3::dom2::stateless Document {
  %NODE%
  %NODE_PROTOTYPE%
  %DOCUMENT%
}

................................................................................
      $myDom Log "XMLHttpRequest readystatechange" $name "event" $rc $msg
    }
  }
}

set ::hv3::dom::next_xmlhttp_id 0
proc ::hv3::dom::newXMLHttpRequest {dom hv3} {


  # Name of the state-array for the new object.
  set statevar "::hv3::DOM::xmlhttprequest_[incr ::hv3::dom::next_xmlhttp_id]"
  upvar #0 $statevar state

  # Intialize the new object state.
  set state(async)          0

Changes to hv/hv3_form.tcl.

1
2
3
4
5
6
7
8
...
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
namespace eval hv3 { set {version($Id: hv3_form.tcl,v 1.97 2008/02/03 11:06:56 danielk1977 Exp $)} 1 }

###########################################################################
# hv3_form.tcl --
#
#     This file contains code to implement Html forms for Tkhtml based
#     browsers. The only requirement is that no other code register for
#     node-handler callbacks for <input>, <button> <select> or <textarea> 
................................................................................
  method ComboboxChanged {widget newValue} {
    set idx [$hull curselection]
    if {$myCurrentSelected<0 || $idx eq "" || $idx == $myCurrentSelected} return
    set myCurrentSelected $idx
    focus [winfo parent $win]

    # Fire the "onchange" dom event.
    [$myHv3 dom] event onchange $myNode
  }

  # This is called by the DOM module whenever the tree-structure 
  # surrounding this element has been modified. Update the
  # state of the widget to reflect the new tree structure.
  method treechanged {} {

|







 







|







1
2
3
4
5
6
7
8
...
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
namespace eval hv3 { set {version($Id: hv3_form.tcl,v 1.98 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

###########################################################################
# hv3_form.tcl --
#
#     This file contains code to implement Html forms for Tkhtml based
#     browsers. The only requirement is that no other code register for
#     node-handler callbacks for <input>, <button> <select> or <textarea> 
................................................................................
  method ComboboxChanged {widget newValue} {
    set idx [$hull curselection]
    if {$myCurrentSelected<0 || $idx eq "" || $idx == $myCurrentSelected} return
    set myCurrentSelected $idx
    focus [winfo parent $win]

    # Fire the "onchange" dom event.
    [$myHv3 dom] event change $myNode
  }

  # This is called by the DOM module whenever the tree-structure 
  # surrounding this element has been modified. Update the
  # state of the widget to reflect the new tree structure.
  method treechanged {} {

Changes to hv/hv3_main.tcl.

1
2
3
4
5
6
7
8
...
405
406
407
408
409
410
411

412
413
414
415
416
417
418
namespace eval hv3 { set {version($Id: hv3_main.tcl,v 1.187 2008/02/09 18:14:20 danielk1977 Exp $)} 1 }

catch {memory init on}

proc sourcefile {file} [string map              \
  [list %HV3_DIR% [file dirname [info script]]] \
{ 
  return [file join {%HV3_DIR%} $file] 
................................................................................
  method configureframe {b} {
    foreach {option var} [list                       \
        -fonttable        options(-fonttable)        \
        -fontscale        options(-fontscale)        \
        -zoom             options(-zoom)             \
        -forcefontmetrics options(-forcefontmetrics) \
        -enableimages     options(-enableimages)     \

    ] {
      if {[$b cget $option] ne [set $var]} {
        $b configure $option [set $var]
      }
    }
  }

|







 







>







1
2
3
4
5
6
7
8
...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
namespace eval hv3 { set {version($Id: hv3_main.tcl,v 1.188 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

catch {memory init on}

proc sourcefile {file} [string map              \
  [list %HV3_DIR% [file dirname [info script]]] \
{ 
  return [file join {%HV3_DIR%} $file] 
................................................................................
  method configureframe {b} {
    foreach {option var} [list                       \
        -fonttable        options(-fonttable)        \
        -fontscale        options(-fontscale)        \
        -zoom             options(-zoom)             \
        -forcefontmetrics options(-forcefontmetrics) \
        -enableimages     options(-enableimages)     \
        -enablejavascript options(-enablejavascript) \
    ] {
      if {[$b cget $option] ne [set $var]} {
        $b configure $option [set $var]
      }
    }
  }

Changes to hv/hv3_notebook.tcl.

1
2
3
4
5
6
7
8
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355

356







357
358
359
360
361
362
363
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
...
401
402
403
404
405
406
407
408

409
410
411
412
413
414
415
namespace eval hv3 { set {version($Id: hv3_notebook.tcl,v 1.10 2008/02/03 17:53:26 danielk1977 Exp $)} 1 }

# This file contains the implementation of three snit widgets:
#
#     ::hv3::notebook_header
#     ::hv3::notebook
#     ::hv3::tabset
#
................................................................................
#     $notebook title WIDGET ?NEW-TITLE?
#
#     <<NotebookTabChanged>>
#
snit::widget ::hv3::notebook {

  variable myWidgets [list]
  variable myCurrent 0

  delegate option * to hull

  component myHeader
  delegate option -closecmd to myHeader
  delegate method title to myHeader
  
................................................................................
  #     Add a new widget to the set of tabbed windows.
  #
  method add {widget {zTitle ""} {update false}} {

    lappend myWidgets $widget

    bind $widget <Destroy> [list $self HandleDestroy $widget %W]
    lower $widget
    raise $widget $myHeader
    if {[llength $myWidgets] == 2} {
      $self Place [lindex $myWidgets 0]
    }
    $self Place $widget

    if {$update} update
    $myHeader add_tab $widget
    $myHeader title $widget $zTitle
    if {[llength $myWidgets] == 1} {
      $myHeader select $widget

    }
  }

  method Place {w} {

    grid $w -row 1 -column 0 -sticky nsew







  }

  method HandleDestroy {widget w} {
    catch {
      if {$widget eq $w} {$self Remove $widget}
    }
  }
................................................................................
    $myHeader del_tab $widget

    if {$idx < $myCurrent || $myCurrent == [llength $myWidgets]} {
      incr myCurrent -1
    }
    if {$myCurrent >= 0} {
      set w [lindex $myWidgets $myCurrent]
      raise $w
      $myHeader select $w
    }

    after cancel [list event generate $win <<NotebookTabChanged>>]
    after idle   [list event generate $win <<NotebookTabChanged>>]
  }

................................................................................
      set idx [lsearch $myWidgets $widget]
      if {$idx < 0} { error "$widget is not managed by $self" }
      if {$myCurrent != $idx} {
        set myCurrent $idx
        $myHeader select $widget
        after cancel [list event generate $win <<NotebookTabChanged>>]
        after idle   [list event generate $win <<NotebookTabChanged>>]
        raise $widget

      }
    }
    return [lindex $myWidgets $myCurrent]
  }

  method tabs {} {
    return $myWidgets
|







 







|







 







<
<
<
<
<
<






>




>

>
>
>
>
>
>
>







 







|







 







|
>







1
2
3
4
5
6
7
8
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
333
334
335
336
337
338
339






340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
...
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
namespace eval hv3 { set {version($Id: hv3_notebook.tcl,v 1.11 2008/02/15 18:23:37 danielk1977 Exp $)} 1 }

# This file contains the implementation of three snit widgets:
#
#     ::hv3::notebook_header
#     ::hv3::notebook
#     ::hv3::tabset
#
................................................................................
#     $notebook title WIDGET ?NEW-TITLE?
#
#     <<NotebookTabChanged>>
#
snit::widget ::hv3::notebook {

  variable myWidgets [list]
  variable myCurrent -1

  delegate option * to hull

  component myHeader
  delegate option -closecmd to myHeader
  delegate method title to myHeader
  
................................................................................
  #     Add a new widget to the set of tabbed windows.
  #
  method add {widget {zTitle ""} {update false}} {

    lappend myWidgets $widget

    bind $widget <Destroy> [list $self HandleDestroy $widget %W]







    if {$update} update
    $myHeader add_tab $widget
    $myHeader title $widget $zTitle
    if {[llength $myWidgets] == 1} {
      $myHeader select $widget
      $self Place $widget
    }
  }

  method Place {w} {
    lower $w
    grid $w -row 1 -column 0 -sticky nsew
    update
    update
    update
    foreach slave [grid slaves $win -row 1 -column 0] {
      if {$w eq $slave} continue
      grid forget $slave
    } 
  }

  method HandleDestroy {widget w} {
    catch {
      if {$widget eq $w} {$self Remove $widget}
    }
  }
................................................................................
    $myHeader del_tab $widget

    if {$idx < $myCurrent || $myCurrent == [llength $myWidgets]} {
      incr myCurrent -1
    }
    if {$myCurrent >= 0} {
      set w [lindex $myWidgets $myCurrent]
      $self Place $w
      $myHeader select $w
    }

    after cancel [list event generate $win <<NotebookTabChanged>>]
    after idle   [list event generate $win <<NotebookTabChanged>>]
  }

................................................................................
      set idx [lsearch $myWidgets $widget]
      if {$idx < 0} { error "$widget is not managed by $self" }
      if {$myCurrent != $idx} {
        set myCurrent $idx
        $myHeader select $widget
        after cancel [list event generate $win <<NotebookTabChanged>>]
        after idle   [list event generate $win <<NotebookTabChanged>>]
        # raise $widget
        $self Place $widget
      }
    }
    return [lindex $myWidgets $myCurrent]
  }

  method tabs {} {
    return $myWidgets

Added hv/hv3bridge.c.









































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

typedef struct BridgeObject BridgeObject;
typedef struct BridgeEnum BridgeEnum;

struct BridgeObject {
  struct SEE_object object;
  struct SEE_interpreter *i;
  struct SEE_object *pObj;
};

struct BridgeEnum {
  struct SEE_enum base;
  struct SEE_interpreter *i;
  struct SEE_enum *pEnum;
};

static struct SEE_objectclass *getBridgeVtbl();
static struct SEE_enumclass *getBridgeEnumVtbl();

/*
 *---------------------------------------------------------------------------
 *
 * createBridgeObject --
 *
 *   This is the only public interface in this file. Return a pointer to
 *   a wrapper (bridge) object that can be used in interpreter pInterp
 *   to access an object pForiegnObj that was created in interpreter
 *   pForiegnInterp.
 *
 * Results:
 *
 * Side effects:
 *
 *---------------------------------------------------------------------------
 */
struct SEE_object *
createBridgeObject(pInterp, pForiegnInterp, pForiegnObj)
    struct SEE_interpreter *pInterp;
    struct SEE_interpreter *pForiegnInterp;
    struct SEE_object *pForiegnObj;
{
    BridgeObject *p;
    if (!pForiegnObj || pForiegnObj->objectclass==getBridgeVtbl()) {
        return pForiegnObj;
    }
    p = SEE_NEW(pInterp, BridgeObject);
    memset(p, 0, sizeof(BridgeObject));
    p->object.Prototype = 0;
    p->object.objectclass = getBridgeVtbl();
    p->i = pForiegnInterp;
    p->pObj = pForiegnObj;
    return (struct SEE_object *)p;
}

static void
copyBridgeValue(pInterp, pValue, pForiegnInterp, pForiegnValue)
    struct SEE_interpreter *pInterp;              /* Source interpreter */
    struct SEE_value *pValue;                     /* Destination value */
    struct SEE_interpreter *pForiegnInterp;       /* Source interpreter */
    struct SEE_value *pForiegnValue;              /* Source value */
{
    int eType = SEE_VALUE_GET_TYPE(pForiegnValue);

    if( eType==SEE_OBJECT ){
        struct SEE_object *o = pForiegnValue->u.object;
        SEE_SET_OBJECT(pValue, createBridgeObject(pInterp, pForiegnInterp, o));
        assert(SEE_VALUE_GET_TYPE(pValue) == eType);
    }else{
        SEE_VALUE_COPY(pValue, pForiegnValue);
    }
}

static void
handleBridgeException(pInterp, pForiegnInterp, pForiegnTry)
    struct SEE_interpreter *pInterp;
    struct SEE_interpreter *pForiegnInterp;
    SEE_try_context_t *pForiegnTry;
{
    struct SEE_value *pForiegnVal = SEE_CAUGHT(*pForiegnTry);
    if (pForiegnVal) {
        struct SEE_value exception;
        struct SEE_traceback *pTrace;
#if 1
printf("throw: ");
SEE_PrintValue(pForiegnInterp, pForiegnVal, stdout);
printf("\n");
SEE_ToString(pForiegnInterp, pForiegnVal, &exception);
SEE_PrintValue(pForiegnInterp, &exception, stdout);
printf("\n");
#endif
#if 0
        for (pTrace = pForiegnTry->traceback; pTrace; pTrace = pTrace->prev) {
            if (!pTrace->prev) {
                pTrace->prev = pInterp->traceback;
                pInterp->traceback = pForiegnTry->traceback;
            }
        }
#endif
        copyBridgeValue(pInterp, &exception, pForiegnInterp, pForiegnVal);
        pInterp->try_location = pForiegnInterp->try_location;
        SEE_THROW(pInterp, &exception);
    }
}


static void 
Bridge_Get(pInterp, pObj, pProp, pRes)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_string *pProp;
    struct SEE_value *pRes;
{
    BridgeObject *p = (BridgeObject *)pObj;
    if (p->i == pInterp) {
        SEE_OBJECT_GET(pInterp, p->pObj, pProp, pRes);
        return;
    } else {
        SEE_try_context_t try_ctxt;
        struct SEE_value val;
        pProp = SEE_intern(p->i, pProp);
        SEE_TRY(p->i, try_ctxt) {
            SEE_OBJECT_GET(p->i, p->pObj, pProp, &val);
            copyBridgeValue(pInterp, pRes, p->i, &val);
        }
        handleBridgeException(pInterp, p->i, &try_ctxt);
    }
}

static void 
Bridge_Put(pInterp, pObj, pProp, pValue, flags)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_string *pProp;
    struct SEE_value *pValue;
    int flags;
{
    BridgeObject *p = (BridgeObject *)pObj;
    if (p->i == pInterp) {
        SEE_OBJECT_PUT(pInterp, p->pObj, pProp, pValue, flags);
        return;
    } else {
        SEE_try_context_t try_ctxt;
        struct SEE_value val;
        pProp = SEE_intern(p->i, pProp);
        copyBridgeValue(p->i, &val, pInterp, pValue);

        SEE_TRY(p->i, try_ctxt) {
            SEE_OBJECT_PUT(p->i, p->pObj, pProp, &val, flags);
        }
        handleBridgeException(pInterp, p->i, &try_ctxt);
    }
}

static int 
Bridge_CanPut(pInterp, pObj, pProp)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_string *pProp;
{
    BridgeObject *p = (BridgeObject *)pObj;
    pProp = SEE_intern(p->i, pProp);
    return SEE_OBJECT_CANPUT(p->i, p->pObj, pProp);
}

static int 
Bridge_HasProperty(pInterp, pObj, pProp)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_string *pProp;
{
    BridgeObject *p = (BridgeObject *)pObj;
    pProp = SEE_intern(p->i, pProp);
    return SEE_OBJECT_HASPROPERTY(p->i, p->pObj, pProp);
}

static int 
Bridge_Delete(pInterp, pObj, pProp)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_string *pProp;
{
    BridgeObject *p = (BridgeObject *)pObj;
    if (p->i == pInterp) {
        return SEE_OBJECT_DELETE(pInterp, p->pObj, pProp);
    } else {
        int ret;
        SEE_try_context_t try_ctxt;
        pProp = SEE_intern(p->i, pProp);
        SEE_TRY(p->i, try_ctxt) {
            ret = SEE_OBJECT_DELETE(p->i, p->pObj, pProp);
        }
        handleBridgeException(pInterp, p->i, &try_ctxt);
        return ret;
    }
}

static void 
Bridge_DefaultValue(pInterp, pObj, pHint, pRes)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_value *pHint;
    struct SEE_value *pRes;
{
    BridgeObject *p = (BridgeObject *)pObj;
    struct SEE_value val;
    SEE_OBJECT_DEFAULTVALUE(p->i, p->pObj, pHint, &val);
    copyBridgeValue(pInterp, pRes, p->i, &val);
}

static struct SEE_enum *
Bridge_Enumerator(pInterp, pObj)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
{
    BridgeObject *p = (BridgeObject *)pObj;
    BridgeEnum *pEnum;

    pEnum = SEE_NEW(pInterp, BridgeEnum);
    pEnum->base.enumclass = getBridgeEnumVtbl();
    pEnum->i = p->i;
    pEnum->pEnum = SEE_OBJECT_ENUMERATOR(p->i, p->pObj);

    return (struct SEE_enum *)pEnum;
}

static void 
bridgeCallOrConstruct(pInterp, pObj, pThis, argc, argv, pRes, isConstruct)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_object *pThis;
    int argc;
    struct SEE_value **argv;
    struct SEE_value *pRes;
    int isConstruct;
{
    BridgeObject *p = (BridgeObject *)pObj;

    if (p->i==pInterp) {
        if (isConstruct) {
            SEE_OBJECT_CONSTRUCT(pInterp, p->pObj, pThis, argc, argv, pRes);
        } else {
            SEE_OBJECT_CALL(pInterp, p->pObj, pThis, argc, argv, pRes);
        }
        return;
    }else{
        SEE_try_context_t try_ctxt;
        struct SEE_value **apValue;
        struct SEE_value *aValue;
        struct SEE_value val;

        int nByte;
        int i;
        nByte = (sizeof(struct SEE_value) + sizeof(struct SEE_value *)) * argc;
        aValue = SEE_malloc(pInterp, nByte);
        apValue = (struct SEE_value **)&aValue[argc];
        for(i = 0; i < argc; i++){
            copyBridgeValue(p->i, &aValue[i], pInterp, argv[i]);
            apValue[i] = &aValue[i];
        }
        pThis = createBridgeObject(p->i, pInterp, pThis);

        SEE_TRY(p->i, try_ctxt) {
            if (isConstruct) {
                SEE_OBJECT_CONSTRUCT(p->i, p->pObj, pThis, argc, apValue, &val);
            } else {
                SEE_OBJECT_CALL(p->i, p->pObj, pThis, argc, apValue, &val);
            }
	    copyBridgeValue(pInterp, pRes, p->i, &val);
        }

        handleBridgeException(pInterp, p->i, &try_ctxt);
    }
}

static void 
Bridge_Construct(pInterp, pObj, pThis, argc, argv, pRes)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_object *pThis;
    int argc;
    struct SEE_value **argv;
    struct SEE_value *pRes;
{
    return bridgeCallOrConstruct(pInterp, pObj, pThis, argc, argv, pRes, 1);
}

static void 
Bridge_Call(pInterp, pObj, pThis, argc, argv, pRes)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_object *pThis;
    int argc;
    struct SEE_value **argv;
    struct SEE_value *pRes;
{
    return bridgeCallOrConstruct(pInterp, pObj, pThis, argc, argv, pRes, 0);
}

static int 
Bridge_HasInstance(pInterp, pObj, pInstance)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_value *pInstance;
{
    BridgeObject *p = (BridgeObject *)pObj;
    struct SEE_value val;
    copyBridgeValue(p->i, &val, pInterp, pInstance);
    return SEE_OBJECT_HASINSTANCE(p->i, p->pObj, &val);
}

static void *
Bridge_GetSecDomain(pInterp, pObj)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
{
    BridgeObject *p = (BridgeObject *)pObj;
    return SEE_OBJECT_GET_SEC_DOMAIN(p->i, p->pObj);
}

static struct SEE_string *
BridgeEnum_Next(pSeeInterp, pEnum, pFlags)
    struct SEE_interpreter *pSeeInterp;
    struct SEE_enum *pEnum;
    int *pFlags;
{
    BridgeEnum *p = (BridgeEnum *)pEnum;
    return SEE_ENUM_NEXT(p->i, p->pEnum, pFlags);
}

static struct SEE_objectclass BridgeObjectVtbl = {
    "Bridge",
    Bridge_Get,
    Bridge_Put,
    Bridge_CanPut,
    Bridge_HasProperty,
    Bridge_Delete,
    Bridge_DefaultValue,
    Bridge_Enumerator,
    Bridge_Construct,
    Bridge_Call,
    Bridge_HasInstance,
    Bridge_GetSecDomain
};
static struct SEE_objectclass *getBridgeVtbl() {
    return &BridgeObjectVtbl;
}

static struct SEE_enumclass BridgeEnumVtbl = {
  0,  /* Unused */
  BridgeEnum_Next
};

static struct SEE_enumclass *getBridgeEnumVtbl() {
    return &BridgeEnumVtbl;
}

Changes to hv/hv3events.c.

151
152
153
154
155
156
157


























158
159
160
161
162
163
164
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
    struct SEE_object *pObj;
{
    if (pObj->objectclass == getVtbl()) {
        return &((SeeTclObject *)pObj)->pTypeList;
    }
    return 0;
}



























/*
 *---------------------------------------------------------------------------
 *
 * runEvent --
 *
 * Results: 
................................................................................
    /* If this is a Tcl based object, run any registered DOM event handlers */
    if (pTclObject) {
        ppET = &pTclObject->pTypeList;
        for (pET = *ppET; pET && pET->zType != zType; pET = pET->pNext);
        for (pL = (pET ? pET->pListenerList: 0); rc && pL; pL = pL->pNext) {
            if (pL->isCapture == isCapture) {
                struct SEE_value r;
                SEE_OBJECT_CALL(interp, pL->pListener, pTarget, 1, &pEvent, &r);
                setBooleanFlag(interp, pEvent->u.object, CALLED_LISTENER, 1);
            }
        }
    }

    /* If this is not the "capturing" phase, run the legacy event-handler. */
    if (!isCapture) {
................................................................................
        SEE_string_append(e, zType);
        e = SEE_intern(interp, e);

        SEE_OBJECT_GET(interp, pLookup, e, &val);
        if (SEE_VALUE_GET_TYPE(&val) == SEE_OBJECT) {
            struct SEE_object *pE = pEvent->u.object;
            struct SEE_value res;
            SEE_OBJECT_CALL(interp, val.u.object, pTarget, 1, &pEvent, &res);
            setBooleanFlag(interp, pE, CALLED_LISTENER, 1);
            rc = valueToBoolean(interp, &res, 1);
            if (!rc) {
                setBooleanFlag(interp, pE, PREVENT_DEFAULT, 1);
                setBooleanFlag(interp, pE, STOP_PROPAGATION, 1);
            }
        }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
    struct SEE_object *pObj;
{
    if (pObj->objectclass == getVtbl()) {
        return &((SeeTclObject *)pObj)->pTypeList;
    }
    return 0;
}

static void
objectCall(pInterp, pObj, pThis, argc, argv, pRes)
    struct SEE_interpreter *pInterp;
    struct SEE_object *pObj;
    struct SEE_object *pThis;
    int argc;
    struct SEE_value **argv;
    struct SEE_value *pRes;
{
#if 1
    SEE_OBJECT_CALL(pInterp, pObj, pThis, argc, argv, pRes);
#else
    SEE_try_context_t try_ctxt;
    SEE_TRY(pInterp, try_ctxt) {
        SEE_OBJECT_CALL(pInterp, pObj, pThis, argc, argv, pRes);
    }
    if (SEE_CAUGHT(try_ctxt)) {
        struct SEE_value str;
        SEE_ToString(pInterp, SEE_CAUGHT(try_ctxt), &str);
        printf("Error in event-handler: ");
        SEE_PrintValue(pInterp, &str, stdout);
        printf("\n");
    } 
#endif
}

/*
 *---------------------------------------------------------------------------
 *
 * runEvent --
 *
 * Results: 
................................................................................
    /* If this is a Tcl based object, run any registered DOM event handlers */
    if (pTclObject) {
        ppET = &pTclObject->pTypeList;
        for (pET = *ppET; pET && pET->zType != zType; pET = pET->pNext);
        for (pL = (pET ? pET->pListenerList: 0); rc && pL; pL = pL->pNext) {
            if (pL->isCapture == isCapture) {
                struct SEE_value r;
                objectCall(interp, pL->pListener, pTarget, 1, &pEvent, &r);
                setBooleanFlag(interp, pEvent->u.object, CALLED_LISTENER, 1);
            }
        }
    }

    /* If this is not the "capturing" phase, run the legacy event-handler. */
    if (!isCapture) {
................................................................................
        SEE_string_append(e, zType);
        e = SEE_intern(interp, e);

        SEE_OBJECT_GET(interp, pLookup, e, &val);
        if (SEE_VALUE_GET_TYPE(&val) == SEE_OBJECT) {
            struct SEE_object *pE = pEvent->u.object;
            struct SEE_value res;
            objectCall(interp, val.u.object, pTarget, 1, &pEvent, &res);
            setBooleanFlag(interp, pE, CALLED_LISTENER, 1);
            rc = valueToBoolean(interp, &res, 1);
            if (!rc) {
                setBooleanFlag(interp, pE, PREVENT_DEFAULT, 1);
                setBooleanFlag(interp, pE, STOP_PROPAGATION, 1);
            }
        }

Changes to hv/hv3see.c.

162
163
164
165
166
167
168


169
170
171
172
173
174
175
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
288
289
290
291
292
293
294
295

296
297
298
299






























































300
301
302
303
304
305
306
...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
814
815
816
817
818
819
820





























821
822
823
824
825
826
827
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
...
972
973
974
975
976
977
978





















979
980
981
982
983
984
985
....
1021
1022
1023
1024
1025
1026
1027



1028

1029
1030
1031
1032
1033
1034
1035
....
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206

1207
1208
1209
1210

1211
1212
1213
1214
1215
1216
1217
....
1298
1299
1300
1301
1302
1303
1304











1305
1306
1307
1308
1309
1310
1311
....
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
....
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654

1655
1656
1657
1658
1659
1660
1661
1662
....
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
....
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
....
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
....
2043
2044
2045
2046
2047
2048
2049



2050
2051
2052

2053
2054


2055
2056
2057
2058

2059
2060
2061
2062
2063









2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
....
2286
2287
2288
2289
2290
2291
2292


2293
2294
2295
2296
2297
2298
2299
#define MIN(x,y) ((x) < (y) ? (x) : (y))

/* File hv3format.c contains the code to uniformly indent javascript
 * text. This is used to make stuff in the debugger more readable, it
 * is not essential (and adds a fair overhead too).
 */
#include "hv3format.c"



typedef struct SeeTclObject SeeTclObject;
typedef struct SeeTclClass SeeTclClass;

typedef struct SeeInterp SeeInterp;
typedef struct SeeJsObject SeeJsObject;
typedef struct SeeTimeout SeeTimeout;
................................................................................
};

/* Size of hash-table. This should be replaced with a dynamic hash 
 * table structure. 
 */
#define OBJECT_HASH_SIZE 257

struct SeeInterp {
    /* The two interpreters - SEE and Tcl. The interp member must be
     * first, so that we can cast between (struct SEE_interpreter *)
     * and (SeeInterp *).
     */
    struct SEE_interpreter interp;
    Tcl_Interp *pTclInterp;

    ClientData pInstrumentData;

    Tcl_Obj *pTclError;

    /* Hash table containing the objects created by the Tcl interpreter
     * that are currently in "persistent" state.
     *
     * This maps from the Tcl command to the SeeTclObject structure.
     * This structure (and the aTclObject[] array along with it) is
     * allocated using GC_MALLOC_UNCOLLECTABLE(), so anything in the
     * following hash-table is not eligible for garbage collection.
     */
    SeeTclObject *aTclObject[OBJECT_HASH_SIZE];

    /* Debugger related stuff. If not NULL, pTrace is the tcl script 
     * to invoke from within the SEE trace-callback. While the pTrace
     * script is executing, pTraceContext is set to a copy of the
     * SEE_context passed to the trace-callback.
     */
    Tcl_Obj *pTrace;
    struct SEE_context *pTraceContext;

    struct SEE_scope *pScope;

    Tcl_Obj *pLog;

    /* Start of a linked list of SeeTimeout structures. See 
    ** included file hv3timeout.c for details.
    */
    int iNextTimeout;

    /* Objects used by the events subsystem. See hv3events.c for details */
    struct SEE_object *pEventPrototype;

    /* Linked list of SeeJsObject structures that will be removed from
     * the aJsObject[] table next time removeTransientRefs() is called.
     *
     * Variable iNextJsObject is used to assign unique integer ids
     * (SeeJsObject.iKey) to SeeJsObject instances as they are created.
     * I am not worried about it wrapping around, as the odds of Hv3
     * running for that long in javascript mode without crashing are
     * vanishingly small.
     */
    int iNextJsObject;
    SeeJsObject *pJsObject;
};
static int iSeeInterp = 0;

typedef struct EventType EventType;

/* Each javascript object created by the Tcl-side is represented by
 * an instance of the following struct.
 */
struct SeeTclObject {
    struct SEE_object object;     /* C Base class - Object */
................................................................................
     * SeeInterp.aTclObject[] hash table. 
     */
    SeeTclObject *pNext;
};

struct SeeTclClass  {
  /* Hash table containing fixed list of properties for this class. Hash
   * table keys are intern'd SEE_string pointers.

   */
  Tcl_HashTable aProperty;
};
































































/* This variable, used for debugging, stores the total number of 
 * SeeTclObject structures currently allocated.
 */
static int iNumSeeTclObject = 0;

/* Entries in the SeeInterp.pJsObject[] linked list are instances of
................................................................................
** The hv3timeout.c module uses the SeeInterp.pTimeout pointer. The
** external interface (called from this file) is:
*/ 
static void interpTimeoutInit(SeeInterp *, SeeTclObject *);
static void interpTimeoutCleanup(SeeInterp *, SeeTclObject *);
#include "hv3timeout.c"

static void interpFunctionInit(SeeInterp *, SeeTclObject *);
#include "hv3function.c"


/*
 *---------------------------------------------------------------------------
 *
 * allocWordArray --
 *
 * Results: 
................................................................................
    }

    if (pMethod) Tcl_DecrRefCount(pMethod);
    if (pProp) Tcl_DecrRefCount(pProp);

    return rc;
}






























/*
 *---------------------------------------------------------------------------
 *
 * newSeeTclObject --
 *
 *     Allocate and return a pointer to a new SeeTclObject structure 
................................................................................
 *---------------------------------------------------------------------------
 */
static SeeTclObject *
newSeeTclObject(pTclSeeInterp, pTclCommand)
    SeeInterp *pTclSeeInterp;
    Tcl_Obj *pTclCommand;
{
    Tcl_CmdInfo info;
    SeeTclObject *p;
    char zBuf[256];

    p = SEE_NEW(&pTclSeeInterp->interp, SeeTclObject);
    memset(p, 0, sizeof(SeeTclObject));
    p->pObj = pTclCommand;
    p->object.objectclass = getVtbl();
    p->object.Prototype = pTclSeeInterp->interp.Object_prototype;

    Tcl_IncrRefCount(p->pObj);
    allocWordArray(pTclSeeInterp, p, 5);

    /* Initialise the native object (used to store native properties) */
    p->pNative = (struct SEE_native *)SEE_native_new(&pTclSeeInterp->interp);

    /* Initialise the class, if any */
    sprintf(zBuf, "%s.class", Tcl_GetString(p->apWord[0]));
    if (Tcl_GetCommandInfo(pTclSeeInterp->pTclInterp, zBuf, &info)){
        p->pClass = (SeeTclClass *)info.objClientData;
    }

    iNumSeeTclObject++;
    return p;
}

/*
 *---------------------------------------------------------------------------
 *
 * finalizeObject --
................................................................................
      rc = objToValue(pTclSeeInterp, apElem[ii+1], &value, 0);
      if (rc != TCL_OK) return 0;
      SEE_OBJECT_PUTA(pSee, pRet, Tcl_GetString(apElem[ii]), &value, 0);
    }

    return pRet;
}






















/*
 *---------------------------------------------------------------------------
 *
 * findOrCreateObject --
 *
 * Results:
................................................................................
    );

    /* If pObject is still NULL, there is no existing object, create a 
     * new SeeTclObject.
     */
    if (!pObject) {
        Tcl_Interp *pTcl = pTclSeeInterp->pTclInterp;



        pObject = newSeeTclObject(pTclSeeInterp, pTclCommand);


        /* Insert the new object into the hash table */
        pObject->pNext = pTclSeeInterp->aTclObject[iSlot];
        pTclSeeInterp->aTclObject[iSlot] = pObject;

        /* Initialise the objects events subsystem. */
        eventTargetInit(pTclSeeInterp, pObject);
................................................................................
        if (nElem == 0) {
            SEE_SET_UNDEFINED(pValue);
        } else {
            int iChoice;
            #define TRANSIENT -124
            #define NATIVE    -123
            #define NODE      -122

            struct ValueType {
                char const *zType;
                int eType;
                int nArg;
            } aType[] = {
                {"undefined", SEE_UNDEFINED, 0}, 
                {"null",      SEE_NULL, 0}, 
                {"number",    SEE_NUMBER, 1}, 
                {"string",    SEE_STRING, 1}, 
                {"boolean",   SEE_BOOLEAN, 1},

                {"object",    SEE_OBJECT, 1},
                {"transient", TRANSIENT, 1},
                {"native",    NATIVE, 1},
                {"node",      NODE, 1},

                {0, 0, 0}
            };

            if (Tcl_GetIndexFromObjStruct(pTclInterp, apElem[0], aType,
                sizeof(struct ValueType), "type", 0, &iChoice) 
            ){
                Tcl_AppendResult(pTclInterp, 
................................................................................

                case NATIVE: {
                    struct SEE_object *pObject;
                    pObject = createNative(pInterp, apElem[1]);
                    SEE_SET_OBJECT(pValue, pObject);
                    break;
                }











            }
        }
    }
    return rc;
}

struct SEE_string *
................................................................................
    struct SEE_interpreter *pSee = &(pTclSeeInterp->interp);
    Tcl_Interp *pTclInterp = pTclSeeInterp->pTclInterp;
    int rc = TCL_OK;
    SEE_try_context_t try_ctxt;

    TclCmdArg aOptions[] = {
      {"-file",      0, 0},              /* 0 */
      {"-window",    0, 0},              /* 1 */
      {"-noresult",  1, 0},              /* 2 */
      {0,            0, 0}
    };

    Tcl_Obj *pFile;                     /* Value passed to -file option */
    Tcl_Obj *pWindow;                   /* Value passed to -window option */
    Tcl_Obj *pCode;                     /* Javascript to evaluate */


    struct SEE_value res;               /* Result of script evaluation */

    if (nArg < 3) {
        Tcl_WrongNumArgs(pTclInterp, 1, apArg, "SUBCOMMAND ...");
        return TCL_ERROR;
    }
    if (processArgs(pTclInterp, aOptions, nArg - 3, &apArg[2])) {
        return TCL_ERROR;
    }
    pCode = apArg[nArg - 1];
    pFile = aOptions[0].pVal;
    pWindow = aOptions[1].pVal;

    memset(&res, 0, sizeof(struct SEE_value));
    Tcl_ResetResult(pTclInterp);

    if (pTclSeeInterp->pTraceContext) {
        /* If there is a trace-context, then this method is being called
         * from within a trace callback. In this case use SEE_context_eval()
................................................................................
        struct SEE_input *pInput = SEE_input_utf8(pSee, Tcl_GetString(pCode));

        if( pFile ){
            pInput->filename = SEE_string_sprintf(
                pSee, "%s", Tcl_GetString(pFile)
            );
        }

        if (pWindow) {
            struct SEE_object *p = 0;
            struct SEE_scope *pScope = 0;
            struct SEE_scope *pScopeOld = pTclSeeInterp->pScope;

            p = findOrCreateObject(pTclSeeInterp, pWindow, 0);
            pScope = (struct SEE_scope *)SEE_malloc(pSee, sizeof(*pScope) * 2);
            pScope->obj = p;
            pScope->next = &pScope[1];
            pScope->next->obj = pTclSeeInterp->interp.Global;
            pScope->next->next = 0;

            pTclSeeInterp->pScope = pScope;
            SEE_TRY(pSee, try_ctxt) {
                SEE_eval(pSee, pInput, p, p, pScope, &res);
            }
            pTclSeeInterp->pScope = pScopeOld;
        } else {
            SEE_TRY(pSee, try_ctxt) {
                SEE_Global_eval(pSee, pInput, &res);
            }
        }
        SEE_INPUT_CLOSE(pInput);
    }

    if (SEE_CAUGHT(try_ctxt)) {
        rc = handleJavascriptError(pTclSeeInterp, &try_ctxt);
    } else if (!aOptions[2].pVal) {
        Tcl_SetObjResult(pTclInterp, primitiveValueToTcl(pTclSeeInterp, &res));
    }

    return rc;
}

static int
interpClear(pTclSeeInterp, objc, objv)
    SeeInterp *pTclSeeInterp;          /* Interpreter */
    int objc;                          /* Number of arguments. */
    Tcl_Obj *CONST objv[];             /* Argument strings. */
{
    struct SEE_object *pObj;
    SeeTclObject *p;

    pObj = findOrCreateObject(pTclSeeInterp,objv[2],0);
    p = (SeeTclObject *)pObj;
    interpTimeoutCleanup(pTclSeeInterp, p);
    assert(p->pTimeout == 0);
    memset(p->pNative->properties, 0, sizeof(p->pNative->properties));
    p->pTypeList = 0;
    interpTimeoutInit(pTclSeeInterp, p);
    interpFunctionInit(pTclSeeInterp, p);

    return TCL_OK;
}

static int
interpSet(pTclSeeInterp, pObject, pProp, pValue)
    SeeInterp *pTclSeeInterp;          /* Interpreter */
    Tcl_Obj *pObject;
    Tcl_Obj *pProp;
    Tcl_Obj *pValue;
{
    SeeTclObject *p;
    struct SEE_value value;
    int rc;
    p = (SeeTclObject *)findOrCreateObject(pTclSeeInterp, pObject, 0);
    rc = objToValue(pTclSeeInterp, pValue, &value, 0);
    if (rc == TCL_OK) {
        SEE_OBJECT_PUTA(&pTclSeeInterp->interp, 

            (struct SEE_object *)(p->pNative), Tcl_GetString(pProp), &value, 0
        );
    }
    return rc;
}

/*
 *---------------------------------------------------------------------------
................................................................................
    int nMin;
    int nMax;

    enum INTERP_enum {
        INTERP_DESTROY,               /* Destroy the interpreter */
        INTERP_EVAL,                  /* Evaluate some javascript */
        INTERP_TOSTRING,              /* Convert js value to a string */
        INTERP_WINDOW,                /* Initialize a "Window" object */
        INTERP_CLEAR,

        INTERP_NODE,
        INTERP_SET,

        /* Object management */
        INTERP_MAKE_TRANSIENT,        /* Declare an object eligible for GC */
        INTERP_MAKE_PERSISTENT,       /* Cancel a previous [make_transient] */

        /* Debugging API - not essential for normal operation. */
        INTERP_DEBUG,
................................................................................
        int nMinArgs;
        int nMaxArgs;
        char *zArgs;
    } aSubCommand[] = {
        {"destroy",     INTERP_DESTROY,     0, 0, ""},
        {"eval",        INTERP_EVAL,        0, -1, 0},
        {"tostring",    INTERP_TOSTRING,    1, 1, "JAVASCRIPT-VALUE"},
        {"window",      INTERP_WINDOW,      1, 1, "JAVASCRIPT-VALUE"},
        {"clear",       INTERP_CLEAR,       1, 1, "JAVASCRIPT-VALUE"},

        {"node",        INTERP_NODE,        1, 1, "TCL-COMMAND"},

        /* Set properties on persistent objects */
        {"set",         INTERP_SET,         3, 3, 
             "JAVASCRIPT-OBJECT PROPERTY JAVASCRIPT-VALUE"},

        /* Events */
        {"dispatch",    INTERP_DISPATCH, 2, 2, "TARGET-COMMAND EVENT-COMMAND"},

        /* Object management */
        {"make_transient",  INTERP_MAKE_TRANSIENT,  1, 1, "TCL-COMMAND"},
        {"make_persistent", INTERP_MAKE_PERSISTENT, 1, 1, "TCL-COMMAND"},
................................................................................
         * seeInterp debug SUB-COMMAND
         */
        case INTERP_DEBUG: {
            rc = interpDebug(pTclSeeInterp, objc, objv);
            break;
        }

        /*
         * seeInterp window JAVASCRIPT-OBJECT
         */
        case INTERP_WINDOW: {
            struct SEE_object *p = findOrCreateObject(pTclSeeInterp,objv[2],0);
            interpTimeoutInit(pTclSeeInterp, (SeeTclObject *)p);
            interpFunctionInit(pTclSeeInterp, (SeeTclObject *)p);
            break;
        }

        /*
         * seeInterp clear JAVASCRIPT-OBJECT
         */
        case INTERP_CLEAR: {
            rc = interpClear(pTclSeeInterp, objc, objv);
            break;
        }

        /*
         * seeInterp node JAVASCRIPT-OBJECT
         */
        case INTERP_NODE: {
            createNode(pTclSeeInterp, objv[2]);
            break;
        }

        /*
         * seeInterp set JAVASCRIPT-OBJECT PROPERTY JAVASCRIPT-VALUE
         */
        case INTERP_SET: {
            rc = interpSet(pTclSeeInterp, objv[2], objv[3], objv[4]);
            break;
        }

        /*
         * seeInterp destroy
         *
         */
................................................................................
    ClientData clientData;             /* Unused */
    Tcl_Interp *interp;                /* Current interpreter. */
    int objc;                          /* Number of arguments. */
    Tcl_Obj *CONST objv[];             /* Argument strings. */
{
    char zCmd[64];
    SeeInterp *pInterp;




    sprintf(zCmd, "::see::interp_%d", iSeeInterp++);


    pInterp = (SeeInterp *)GC_MALLOC_UNCOLLECTABLE(sizeof(SeeInterp));
    memset(pInterp, 0, sizeof(SeeInterp));


 
    /* Initialize a new SEE interpreter */
    SEE_interpreter_init_compat(&pInterp->interp, 
        SEE_COMPAT_JS15|SEE_COMPAT_SGMLCOM|SEE_COMPAT_262_3B

    );
    pInterp->interp.trace = seeTraceHook;

    /* Initialise the pTclInterp field. */
    pInterp->pTclInterp = interp;










#ifndef NDEBUG
    if (1) {
        Tcl_CmdInfo cmdinfo;
        if (Tcl_GetCommandInfo(interp, "::tkhtml::instrument", &cmdinfo)) {
            pInterp->pInstrumentData = cmdinfo.objClientData;
        }
    }
#endif

    Tcl_CreateObjCommand(interp, zCmd, interpCmd, pInterp, delInterpCmd);
    Tcl_SetResult(interp, zCmd, TCL_VOLATILE);
    return TCL_OK;
}

static void throwTclError(p, rc)
    struct SEE_interpreter *p;
    int rc;
{
................................................................................
    struct SEE_string *pProp;
{
    SeeTclObject *p = (SeeTclObject *)pObj;
    SeeInterp *pTclSeeInterp = (SeeInterp *)pInterp;
    int rc;
    int ret = 0;
    struct SEE_object *pNative = (struct SEE_object *)p->pNative;



    /* First check if the property is stored in the native hash table. */
    pProp = SEE_intern(pInterp, pProp);
    ret = SEE_OBJECT_HASPROPERTY(pInterp, pNative, pProp);

    if (!ret && (
        !p->pClass || Tcl_FindHashEntry(&p->pClass->aProperty, (char *)pProp)







>
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
|
>







 







>










>




>







 







>
>
>
>
>
>
>
>
>
>
>







 







<
|


>

<

>












|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<






|







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<



<


<



>
|







 







<
<


|







 







<
<




|
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









|

|
|







 







>
>
>
|
<

>


>
>

|
|
|
>



|
|
>
>
>
>
>
>
>
>
>










<
<







 







>
>







162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
184
185
186
187
188
189
190
























































191
192
193
194
195
196
197
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
...
342
343
344
345
346
347
348



349
350
351
352
353
354
355
...
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
...
871
872
873
874
875
876
877




878






879











880
881
882
883
884
885
886
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
....
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
....
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
....
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
....
1589
1590
1591
1592
1593
1594
1595

1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
....
1631
1632
1633
1634
1635
1636
1637














1638





1639

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653





















1654
1655

1656
1657
1658

1659
1660

1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
....
1770
1771
1772
1773
1774
1775
1776


1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
....
1798
1799
1800
1801
1802
1803
1804


1805
1806
1807
1808
1809

1810
1811
1812
1813
1814
1815
1816
....
1856
1857
1858
1859
1860
1861
1862


















1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
....
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040

2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075


2076
2077
2078
2079
2080
2081
2082
....
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
#define MIN(x,y) ((x) < (y) ? (x) : (y))

/* File hv3format.c contains the code to uniformly indent javascript
 * text. This is used to make stuff in the debugger more readable, it
 * is not essential (and adds a fair overhead too).
 */
#include "hv3format.c"

#include "hv3bridge.c"

typedef struct SeeTclObject SeeTclObject;
typedef struct SeeTclClass SeeTclClass;

typedef struct SeeInterp SeeInterp;
typedef struct SeeJsObject SeeJsObject;
typedef struct SeeTimeout SeeTimeout;
................................................................................
};

/* Size of hash-table. This should be replaced with a dynamic hash 
 * table structure. 
 */
#define OBJECT_HASH_SIZE 257

























































typedef struct EventType EventType;

/* Each javascript object created by the Tcl-side is represented by
 * an instance of the following struct.
 */
struct SeeTclObject {
    struct SEE_object object;     /* C Base class - Object */
................................................................................
     * SeeInterp.aTclObject[] hash table. 
     */
    SeeTclObject *pNext;
};

struct SeeTclClass  {
  /* Hash table containing fixed list of properties for this class. Hash
   * table keys are intern'd SEE_string pointers. Because they are intern'd
   * in the global string table, this can be used with any SEE interpreter.
   */
  Tcl_HashTable aProperty;
};


struct SeeInterp {
    /* The two interpreters - SEE and Tcl. The interp member must be
     * first, so that we can cast between (struct SEE_interpreter *)
     * and (SeeInterp *).
     */
    struct SEE_interpreter interp;

    /* The Tcl interpreter that created this object. */
    Tcl_Interp *pTclInterp;

    /* The global object used by this interpreter. */
    SeeTclObject global;

    ClientData pInstrumentData;

    Tcl_Obj *pTclError;

    /* Hash table containing the objects created by the Tcl interpreter
     * that are currently in "persistent" state.
     *
     * This maps from the Tcl command to the SeeTclObject structure.
     * This structure (and the aTclObject[] array along with it) is
     * allocated using GC_MALLOC_UNCOLLECTABLE(), so anything in the
     * following hash-table is not eligible for garbage collection.
     */
    SeeTclObject *aTclObject[OBJECT_HASH_SIZE];

    /* Debugger related stuff. If not NULL, pTrace is the tcl script 
     * to invoke from within the SEE trace-callback. While the pTrace
     * script is executing, pTraceContext is set to a copy of the
     * SEE_context passed to the trace-callback.
     */
    Tcl_Obj *pTrace;
    struct SEE_context *pTraceContext;

    struct SEE_scope *pScope;

    Tcl_Obj *pLog;

    /* Start of a linked list of SeeTimeout structures. See 
    ** included file hv3timeout.c for details.
    */
    int iNextTimeout;

    /* Objects used by the events subsystem. See hv3events.c for details */
    struct SEE_object *pEventPrototype;

    /* Linked list of SeeJsObject structures that will be removed from
     * the aJsObject[] table next time removeTransientRefs() is called.
     *
     * Variable iNextJsObject is used to assign unique integer ids
     * (SeeJsObject.iKey) to SeeJsObject instances as they are created.
     * I am not worried about it wrapping around, as the odds of Hv3
     * running for that long in javascript mode without crashing are
     * vanishingly small.
     */
    int iNextJsObject;
    SeeJsObject *pJsObject;
};
static int iSeeInterp = 0;


/* This variable, used for debugging, stores the total number of 
 * SeeTclObject structures currently allocated.
 */
static int iNumSeeTclObject = 0;

/* Entries in the SeeInterp.pJsObject[] linked list are instances of
................................................................................
** The hv3timeout.c module uses the SeeInterp.pTimeout pointer. The
** external interface (called from this file) is:
*/ 
static void interpTimeoutInit(SeeInterp *, SeeTclObject *);
static void interpTimeoutCleanup(SeeInterp *, SeeTclObject *);
#include "hv3timeout.c"





/*
 *---------------------------------------------------------------------------
 *
 * allocWordArray --
 *
 * Results: 
................................................................................
    }

    if (pMethod) Tcl_DecrRefCount(pMethod);
    if (pProp) Tcl_DecrRefCount(pProp);

    return rc;
}

static void
initSeeTclObject(pTclSeeInterp, p, pTclCommand)
    SeeInterp *pTclSeeInterp;
    SeeTclObject *p;
    Tcl_Obj *pTclCommand;
{
    Tcl_CmdInfo info;
    char zBuf[256];

    memset(p, 0, sizeof(SeeTclObject));
    p->pObj = pTclCommand;
    p->object.objectclass = getVtbl();
    p->object.Prototype = pTclSeeInterp->interp.Object_prototype;

    Tcl_IncrRefCount(p->pObj);
    allocWordArray(pTclSeeInterp, p, 5);

    /* Initialise the native object (used to store native properties) */
    p->pNative = (struct SEE_native *)SEE_native_new(&pTclSeeInterp->interp);

    /* Initialise the class, if any */
    sprintf(zBuf, "%s.class", Tcl_GetString(p->apWord[0]));
    if (Tcl_GetCommandInfo(pTclSeeInterp->pTclInterp, zBuf, &info)){
        p->pClass = (SeeTclClass *)info.objClientData;
    }

    iNumSeeTclObject++;
}

/*
 *---------------------------------------------------------------------------
 *
 * newSeeTclObject --
 *
 *     Allocate and return a pointer to a new SeeTclObject structure 
................................................................................
 *---------------------------------------------------------------------------
 */
static SeeTclObject *
newSeeTclObject(pTclSeeInterp, pTclCommand)
    SeeInterp *pTclSeeInterp;
    Tcl_Obj *pTclCommand;
{




    SeeTclObject *p = SEE_NEW(&pTclSeeInterp->interp, SeeTclObject);






    initSeeTclObject(pTclSeeInterp, p, pTclCommand);











    return p;
}

/*
 *---------------------------------------------------------------------------
 *
 * finalizeObject --
................................................................................
      rc = objToValue(pTclSeeInterp, apElem[ii+1], &value, 0);
      if (rc != TCL_OK) return 0;
      SEE_OBJECT_PUTA(pSee, pRet, Tcl_GetString(apElem[ii]), &value, 0);
    }

    return pRet;
}

static struct SEE_object *
createBridge(pTclSeeInterp, pCommand)
    SeeInterp *pTclSeeInterp;
    Tcl_Obj *pCommand;
{
    Tcl_Command t;
    Tcl_CmdInfo info;

    SeeInterp *pForiegnInterp;

    t = Tcl_GetCommandFromObj(pTclSeeInterp->pTclInterp, pCommand);
    if( !t ) return 0;
    assert(t);
    Tcl_GetCommandInfoFromToken(t, &info);
    pForiegnInterp = info.objClientData;
    assert( pForiegnInterp->global.object.objectclass==getVtbl() );
    return createBridgeObject(&pTclSeeInterp->interp, 
        &pForiegnInterp->interp, &pForiegnInterp->global.object
    );
}

/*
 *---------------------------------------------------------------------------
 *
 * findOrCreateObject --
 *
 * Results:
................................................................................
    );

    /* If pObject is still NULL, there is no existing object, create a 
     * new SeeTclObject.
     */
    if (!pObject) {
        Tcl_Interp *pTcl = pTclSeeInterp->pTclInterp;
        if (isGlobal) {
            pObject = &pTclSeeInterp->global;
        }else{
            pObject = newSeeTclObject(pTclSeeInterp, pTclCommand);
        }

        /* Insert the new object into the hash table */
        pObject->pNext = pTclSeeInterp->aTclObject[iSlot];
        pTclSeeInterp->aTclObject[iSlot] = pObject;

        /* Initialise the objects events subsystem. */
        eventTargetInit(pTclSeeInterp, pObject);
................................................................................
        if (nElem == 0) {
            SEE_SET_UNDEFINED(pValue);
        } else {
            int iChoice;
            #define TRANSIENT -124
            #define NATIVE    -123
            #define NODE      -122
            #define BRIDGE    -121
            struct ValueType {
                char const *zType;
                int eType;
                int nArg;
            } aType[] = {
                {"undefined", SEE_UNDEFINED, 0}, 
                {"null",      SEE_NULL, 0}, 
                {"number",    SEE_NUMBER, 1}, 
                {"string",    SEE_STRING, 1}, 
                {"boolean",   SEE_BOOLEAN, 1},

                {"object",    SEE_OBJECT, 1},
                {"transient", TRANSIENT, 1},
                {"native",    NATIVE, 1},
                {"node",      NODE, 1},
                {"bridge",    BRIDGE, 1},
                {0, 0, 0}
            };

            if (Tcl_GetIndexFromObjStruct(pTclInterp, apElem[0], aType,
                sizeof(struct ValueType), "type", 0, &iChoice) 
            ){
                Tcl_AppendResult(pTclInterp, 
................................................................................

                case NATIVE: {
                    struct SEE_object *pObject;
                    pObject = createNative(pInterp, apElem[1]);
                    SEE_SET_OBJECT(pValue, pObject);
                    break;
                }

                case BRIDGE: {
                    struct SEE_object *pObject;
                    pObject = createBridge(pInterp, apElem[1]);
                    if (pObject) {
                        SEE_SET_OBJECT(pValue, pObject);
                    }else{
                        rc = TCL_ERROR;
                    }
                    break;
                }
            }
        }
    }
    return rc;
}

struct SEE_string *
................................................................................
    struct SEE_interpreter *pSee = &(pTclSeeInterp->interp);
    Tcl_Interp *pTclInterp = pTclSeeInterp->pTclInterp;
    int rc = TCL_OK;
    SEE_try_context_t try_ctxt;

    TclCmdArg aOptions[] = {
      {"-file",      0, 0},              /* 0 */

      {"-noresult",  1, 0},              /* 1 */
      {0,            0, 0}
    };

    Tcl_Obj *pFile;                     /* Value passed to -file option */

    Tcl_Obj *pCode;                     /* Javascript to evaluate */
    int isNoResult;                     /* True if -noresult */

    struct SEE_value res;               /* Result of script evaluation */

    if (nArg < 3) {
        Tcl_WrongNumArgs(pTclInterp, 1, apArg, "SUBCOMMAND ...");
        return TCL_ERROR;
    }
    if (processArgs(pTclInterp, aOptions, nArg - 3, &apArg[2])) {
        return TCL_ERROR;
    }
    pCode = apArg[nArg - 1];
    pFile = aOptions[0].pVal;
    isNoResult = (aOptions[1].pVal!=0);

    memset(&res, 0, sizeof(struct SEE_value));
    Tcl_ResetResult(pTclInterp);

    if (pTclSeeInterp->pTraceContext) {
        /* If there is a trace-context, then this method is being called
         * from within a trace callback. In this case use SEE_context_eval()
................................................................................
        struct SEE_input *pInput = SEE_input_utf8(pSee, Tcl_GetString(pCode));

        if( pFile ){
            pInput->filename = SEE_string_sprintf(
                pSee, "%s", Tcl_GetString(pFile)
            );
        }














        SEE_TRY(pSee, try_ctxt) {





            SEE_Global_eval(pSee, pInput, &res);

        }
        SEE_INPUT_CLOSE(pInput);
    }

    if (SEE_CAUGHT(try_ctxt)) {
        rc = handleJavascriptError(pTclSeeInterp, &try_ctxt);
    } else if (!isNoResult) {
        Tcl_SetObjResult(pTclInterp, primitiveValueToTcl(pTclSeeInterp, &res));
    }

    return rc;
}

static int





















interpGlobalSet(pTclSeeInterp, pProp, pValue)
    SeeInterp *pTclSeeInterp;          /* Interpreter */

    Tcl_Obj *pProp;
    Tcl_Obj *pValue;
{

    struct SEE_value value;
    int rc;

    rc = objToValue(pTclSeeInterp, pValue, &value, 0);
    if (rc == TCL_OK) {
        SEE_OBJECT_PUTA(&pTclSeeInterp->interp, 
            (struct SEE_object *)(pTclSeeInterp->global.pNative), 
            Tcl_GetString(pProp), &value, 0
        );
    }
    return rc;
}

/*
 *---------------------------------------------------------------------------
................................................................................
    int nMin;
    int nMax;

    enum INTERP_enum {
        INTERP_DESTROY,               /* Destroy the interpreter */
        INTERP_EVAL,                  /* Evaluate some javascript */
        INTERP_TOSTRING,              /* Convert js value to a string */



        INTERP_NODE,
        INTERP_GLOBAL,

        /* Object management */
        INTERP_MAKE_TRANSIENT,        /* Declare an object eligible for GC */
        INTERP_MAKE_PERSISTENT,       /* Cancel a previous [make_transient] */

        /* Debugging API - not essential for normal operation. */
        INTERP_DEBUG,
................................................................................
        int nMinArgs;
        int nMaxArgs;
        char *zArgs;
    } aSubCommand[] = {
        {"destroy",     INTERP_DESTROY,     0, 0, ""},
        {"eval",        INTERP_EVAL,        0, -1, 0},
        {"tostring",    INTERP_TOSTRING,    1, 1, "JAVASCRIPT-VALUE"},



        {"node",        INTERP_NODE,        1, 1, "TCL-COMMAND"},

        /* Set properties on persistent objects */
        {"global",      INTERP_GLOBAL,      2, 2, "PROPERTY JAVASCRIPT-VALUE"},


        /* Events */
        {"dispatch",    INTERP_DISPATCH, 2, 2, "TARGET-COMMAND EVENT-COMMAND"},

        /* Object management */
        {"make_transient",  INTERP_MAKE_TRANSIENT,  1, 1, "TCL-COMMAND"},
        {"make_persistent", INTERP_MAKE_PERSISTENT, 1, 1, "TCL-COMMAND"},
................................................................................
         * seeInterp debug SUB-COMMAND
         */
        case INTERP_DEBUG: {
            rc = interpDebug(pTclSeeInterp, objc, objv);
            break;
        }



















        /*
         * seeInterp node JAVASCRIPT-OBJECT
         */
        case INTERP_NODE: {
            createNode(pTclSeeInterp, objv[2]);
            break;
        }

        /*
         * seeInterp global PROPERTY JAVASCRIPT-VALUE
         */
        case INTERP_GLOBAL: {
            rc = interpGlobalSet(pTclSeeInterp, objv[2], objv[3]);
            break;
        }

        /*
         * seeInterp destroy
         *
         */
................................................................................
    ClientData clientData;             /* Unused */
    Tcl_Interp *interp;                /* Current interpreter. */
    int objc;                          /* Number of arguments. */
    Tcl_Obj *CONST objv[];             /* Argument strings. */
{
    char zCmd[64];
    SeeInterp *pInterp;
    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "GLOBAL-OBJCOMMAND");
        return TCL_ERROR;
    }


    /* Allocate the interpreter structure and initialize the global object. */
    pInterp = (SeeInterp *)GC_MALLOC_UNCOLLECTABLE(sizeof(SeeInterp));
    memset(pInterp, 0, sizeof(SeeInterp));
    pInterp->pTclInterp = interp;
    initSeeTclObject(pInterp, &pInterp->global, objv[1]);
 
    /* Initialize the SEE interpreter. */
    SEE_interpreter_init_hostglobal(&pInterp->interp, 
        SEE_COMPAT_JS15|SEE_COMPAT_SGMLCOM|SEE_COMPAT_262_3B,
	(struct SEE_object *)&pInterp->global
    );
    pInterp->interp.trace = seeTraceHook;

    /* This call puts the global object in the hash table with the other
     * Tcl based objects. This is required so that references to 'window'
     * actually return a pointer to SEE_interpreter.Global.
     */
    findOrCreateObject(pInterp, objv[1], 1);
    interpTimeoutInit(pInterp, &pInterp->global);

    /* Create the tcl command used to access this javascript interpreter. */
    sprintf(zCmd, "::see::interp_%d", iSeeInterp++);
    Tcl_CreateObjCommand(interp, zCmd, interpCmd, pInterp, delInterpCmd);
    Tcl_SetResult(interp, zCmd, TCL_VOLATILE);

#ifndef NDEBUG
    if (1) {
        Tcl_CmdInfo cmdinfo;
        if (Tcl_GetCommandInfo(interp, "::tkhtml::instrument", &cmdinfo)) {
            pInterp->pInstrumentData = cmdinfo.objClientData;
        }
    }
#endif



    return TCL_OK;
}

static void throwTclError(p, rc)
    struct SEE_interpreter *p;
    int rc;
{
................................................................................
    struct SEE_string *pProp;
{
    SeeTclObject *p = (SeeTclObject *)pObj;
    SeeInterp *pTclSeeInterp = (SeeInterp *)pInterp;
    int rc;
    int ret = 0;
    struct SEE_object *pNative = (struct SEE_object *)p->pNative;

    if (p == &pTclSeeInterp->global) return 1;

    /* First check if the property is stored in the native hash table. */
    pProp = SEE_intern(pInterp, pProp);
    ret = SEE_OBJECT_HASPROPERTY(pInterp, pNative, pProp);

    if (!ret && (
        !p->pClass || Tcl_FindHashEntry(&p->pClass->aProperty, (char *)pProp)

Changes to main.mk.

189
190
191
192
193
194
195
196
197
198
199
200
201
	@echo '$$(MKSHLIB) tclsee.o $(JSLIB) -o $(JS_SHARED_LIB)'
	@$(MKSHLIB) tclsee.o $(JSLIB) $(TCLSTUBSLIB) -o $(JS_SHARED_LIB)
	@echo '$$(STRIP) $(JS_SHARED_LIB)'
	@$(STRIP) $(JS_SHARED_LIB)
	mv $(JS_SHARED_LIB) tclsee0.1
	echo 'package ifneeded Tclsee 0.1 [list load [file join $$dir $(JS_SHARED_LIB)]]' > tclsee0.1/pkgIndex.tcl

tclsee.o: $(TOP)/hv/hv3see.c $(TOP)/hv/hv3format.c $(TOP)/hv/hv3events.c $(TOP)/hv/hv3timeout.c $(TOP)/hv/hv3function.c
	@echo '$$(COMPILE) $(JSFLAGS) -c $(TOP)/hv/hv3see.c -o $@'
	@$(COMPILE) $(JSFLAGS) -c $(TOP)/hv/hv3see.c -o $@
#
#-----------------------------------------------------------------------








|





189
190
191
192
193
194
195
196
197
198
199
200
201
	@echo '$$(MKSHLIB) tclsee.o $(JSLIB) -o $(JS_SHARED_LIB)'
	@$(MKSHLIB) tclsee.o $(JSLIB) $(TCLSTUBSLIB) -o $(JS_SHARED_LIB)
	@echo '$$(STRIP) $(JS_SHARED_LIB)'
	@$(STRIP) $(JS_SHARED_LIB)
	mv $(JS_SHARED_LIB) tclsee0.1
	echo 'package ifneeded Tclsee 0.1 [list load [file join $$dir $(JS_SHARED_LIB)]]' > tclsee0.1/pkgIndex.tcl

tclsee.o: $(TOP)/hv/hv3see.c $(TOP)/hv/hv3format.c $(TOP)/hv/hv3events.c $(TOP)/hv/hv3timeout.c $(TOP)/hv/hv3bridge.c
	@echo '$$(COMPILE) $(JSFLAGS) -c $(TOP)/hv/hv3see.c -o $@'
	@$(COMPILE) $(JSFLAGS) -c $(TOP)/hv/hv3see.c -o $@
#
#-----------------------------------------------------------------------

Changes to src/html.css.

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
192
193
194
195
196
197
198
199


200
201
202
203
204
205
206
}

INPUT[type="image"][src] { -tkhtml-replacement-image: attr(src) }

/*
 * Default style for buttons created using <input> elements.
 */
INPUT[type="submit"],INPUT[type="button"] {
  display: -tkhtml-inline-button;
  border: 2px solid;
  border-color: #ffffff #828282 #828282 #ffffff;
  background-color: #d9d9d9;
  color: #000000;
  /* padding: 3px 10px 1px 10px; */
  padding: 3px 3px 1px 3px;
................................................................................
  color:               tcl(::tkhtml::if_disabled #666666 #000000);
}
INPUT[type="submit"]:after,INPUT[type="button"]:after {
  content: attr(value);
  position: relative;
}

INPUT[type="submit"]:hover:active,INPUT[type="button"]:hover:active {


  border-top-color:    tcl(::tkhtml::if_disabled #ffffff #828282);
  border-left-color:   tcl(::tkhtml::if_disabled #ffffff #828282);
  border-right-color:  tcl(::tkhtml::if_disabled #828282 #ffffff);
  border-bottom-color: tcl(::tkhtml::if_disabled #828282 #ffffff);
}

INPUT[size] { width: tcl(::tkhtml::inputsize_to_css) }







|







 







|
>
>







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
}

INPUT[type="image"][src] { -tkhtml-replacement-image: attr(src) }

/*
 * Default style for buttons created using <input> elements.
 */
INPUT[type="submit"],INPUT[type="button"],button {
  display: -tkhtml-inline-button;
  border: 2px solid;
  border-color: #ffffff #828282 #828282 #ffffff;
  background-color: #d9d9d9;
  color: #000000;
  /* padding: 3px 10px 1px 10px; */
  padding: 3px 3px 1px 3px;
................................................................................
  color:               tcl(::tkhtml::if_disabled #666666 #000000);
}
INPUT[type="submit"]:after,INPUT[type="button"]:after {
  content: attr(value);
  position: relative;
}

INPUT[type="submit"]:hover:active,
INPUT[type="button"]:hover:active,
button:hover:active {
  border-top-color:    tcl(::tkhtml::if_disabled #ffffff #828282);
  border-left-color:   tcl(::tkhtml::if_disabled #ffffff #828282);
  border-right-color:  tcl(::tkhtml::if_disabled #828282 #ffffff);
  border-bottom-color: tcl(::tkhtml::if_disabled #828282 #ffffff);
}

INPUT[size] { width: tcl(::tkhtml::inputsize_to_css) }

Changes to tools/browsertester.tcl.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

      document.body.innerHTML = form

      document.getElementById("testresult").value = res
      document.getElementById("testform").submit()
    }

    window.onload = runtest
  </SCRIPT>

  %TESTBODY%

</BODY>
}








|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

      document.body.innerHTML = form

      document.getElementById("testresult").value = res
      document.getElementById("testform").submit()
    }

    onload = runtest
  </SCRIPT>

  %TESTBODY%

</BODY>
}